<?xml version="1.0" encoding="UTF-8"?>
<rss  xmlns:atom="http://www.w3.org/2005/Atom" 
      xmlns:media="http://search.yahoo.com/mrss/" 
      xmlns:content="http://purl.org/rss/1.0/modules/content/" 
      xmlns:dc="http://purl.org/dc/elements/1.1/" 
      version="2.0">
<channel>
<title>CanvasXpress Recipes</title>
<link>https://neuhausi.github.io/canvasxpress-blog/</link>
<atom:link href="https://neuhausi.github.io/canvasxpress-blog/index.xml" rel="self" type="application/rss+xml"/>
<description>Interactive, reproducible scientific visualization with canvasXpress — in R, Python and JavaScript.</description>
<generator>quarto-1.6.39</generator>
<lastBuildDate>Fri, 06 Nov 2026 05:00:00 GMT</lastBuildDate>
<item>
  <title>Interactive, reproducible figures inside teal</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/r/interactive-figures-in-teal/</link>
  <description><![CDATA[ 




<p>If you build Shiny apps with <a href="https://github.com/insightsengineering/teal">teal</a>, you know <code>plot_with_settings</code> — the module that wraps a plot with resize, full-screen, and download controls. Until now it rendered only <em>static</em> R graphics: ggplot, lattice, grob, base. Return anything else from <code>plot_r</code> and it quietly fell through and never drew.</p>
<p>That leaves a gap. The analyst looking at a volcano plot, a Kaplan–Meier curve, or a forest plot often wants to hover a point, select a group, and take the exact figure with them — not screenshot a PNG. In a submission-grade workflow they also want that figure to be <em>reproducible</em>: the chart and the code that made it, together.</p>
<section id="a-small-change-with-a-big-surface" class="level2">
<h2 class="anchored" data-anchor-id="a-small-change-with-a-big-surface">A small change with a big surface</h2>
<p><a href="https://github.com/pharmaverse/teal.widgets/pull/371">A PR on teal.widgets</a> adds a render path for interactive <strong>htmlwidgets</strong>. If <code>plot_r()</code> returns an htmlwidget — canvasXpress, plotly, anything with a Shiny binding — <code>plot_with_settings</code> renders it through the widget’s own binding, keeping the familiar card chrome. Height, width, and full-screen work as before, and <strong>download produces a self-contained HTML file</strong> you can email or archive.</p>
<p>It is strictly <strong>opt-in</strong>. Every existing static-plot caller behaves exactly as it did; the interactive path triggers only when a module author chooses to return a widget.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(shiny)</span>
<span id="cb1-2"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(canvasXpress)</span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(teal.widgets)</span>
<span id="cb1-4"></span>
<span id="cb1-5">pg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>(palmerpenguins<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>penguins))</span>
<span id="cb1-6"></span>
<span id="cb1-7">ui <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> bslib<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">page_fluid</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot_with_settings_ui</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p"</span>))</span>
<span id="cb1-8"></span>
<span id="cb1-9">server <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(input, output, session) {</span>
<span id="cb1-10">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot_with_settings_srv</span>(</span>
<span id="cb1-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p"</span>,</span>
<span id="cb1-12">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot_r =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reactive</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">canvasXpress</span>(</span>
<span id="cb1-13">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> pg, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span>,</span>
<span id="cb1-14">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xAxis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"flipper_length_mm"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yAxis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"body_mass_g"</span>),</span>
<span id="cb1-15">      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colorBy =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"species"</span></span>
<span id="cb1-16">    ))</span>
<span id="cb1-17">  )</span>
<span id="cb1-18">}</span>
<span id="cb1-19"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">shinyApp</span>(ui, server)</span></code></pre></div>
</div>
<p>The chart that lands in the card is a real canvasXpress widget — the same one you can render on its own here. Hover a point, click to select, use the toolbar to export:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(canvasXpress)</span>
<span id="cb2-2"></span>
<span id="cb2-3">pg <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.data.frame</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">na.omit</span>(palmerpenguins<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span>penguins))</span>
<span id="cb2-4"></span>
<span id="cb2-5"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">canvasXpress</span>(</span>
<span id="cb2-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data      =</span> pg,</span>
<span id="cb2-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span>,</span>
<span id="cb2-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xAxis     =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"flipper_length_mm"</span>),</span>
<span id="cb2-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yAxis     =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"body_mass_g"</span>),</span>
<span id="cb2-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colorBy   =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"species"</span>,</span>
<span id="cb2-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title     =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Palmer penguins — flipper length vs body mass"</span></span>
<span id="cb2-12">)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-1f02dc9b53bfcfc60a3f" style="width:100%;height:433px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-1f02dc9b53bfcfc60a3f">{"x":{"data":{"y":{"vars":["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52","53","54","55","56","57","58","59","60","61","62","63","64","65","66","67","68","69","70","71","72","73","74","75","76","77","78","79","80","81","82","83","84","85","86","87","88","89","90","91","92","93","94","95","96","97","98","99","100","101","102","103","104","105","106","107","108","109","110","111","112","113","114","115","116","117","118","119","120","121","122","123","124","125","126","127","128","129","130","131","132","133","134","135","136","137","138","139","140","141","142","143","144","145","146","147","148","149","150","151","152","153","154","155","156","157","158","159","160","161","162","163","164","165","166","167","168","169","170","171","172","173","174","175","176","177","178","179","180","181","182","183","184","185","186","187","188","189","190","191","192","193","194","195","196","197","198","199","200","201","202","203","204","205","206","207","208","209","210","211","212","213","214","215","216","217","218","219","220","221","222","223","224","225","226","227","228","229","230","231","232","233","234","235","236","237","238","239","240","241","242","243","244","245","246","247","248","249","250","251","252","253","254","255","256","257","258","259","260","261","262","263","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"],"smps":["species","island","bill_length_mm","bill_depth_mm","flipper_length_mm","body_mass_g","sex","year"],"data":[["Adelie","Torgersen","39.1","18.7","181","3750","male","2007"],["Adelie","Torgersen","39.5","17.4","186","3800","female","2007"],["Adelie","Torgersen","40.3","18.0","195","3250","female","2007"],["Adelie","Torgersen","36.7","19.3","193","3450","female","2007"],["Adelie","Torgersen","39.3","20.6","190","3650","male","2007"],["Adelie","Torgersen","38.9","17.8","181","3625","female","2007"],["Adelie","Torgersen","39.2","19.6","195","4675","male","2007"],["Adelie","Torgersen","41.1","17.6","182","3200","female","2007"],["Adelie","Torgersen","38.6","21.2","191","3800","male","2007"],["Adelie","Torgersen","34.6","21.1","198","4400","male","2007"],["Adelie","Torgersen","36.6","17.8","185","3700","female","2007"],["Adelie","Torgersen","38.7","19.0","195","3450","female","2007"],["Adelie","Torgersen","42.5","20.7","197","4500","male","2007"],["Adelie","Torgersen","34.4","18.4","184","3325","female","2007"],["Adelie","Torgersen","46.0","21.5","194","4200","male","2007"],["Adelie","Biscoe","37.8","18.3","174","3400","female","2007"],["Adelie","Biscoe","37.7","18.7","180","3600","male","2007"],["Adelie","Biscoe","35.9","19.2","189","3800","female","2007"],["Adelie","Biscoe","38.2","18.1","185","3950","male","2007"],["Adelie","Biscoe","38.8","17.2","180","3800","male","2007"],["Adelie","Biscoe","35.3","18.9","187","3800","female","2007"],["Adelie","Biscoe","40.6","18.6","183","3550","male","2007"],["Adelie","Biscoe","40.5","17.9","187","3200","female","2007"],["Adelie","Biscoe","37.9","18.6","172","3150","female","2007"],["Adelie","Biscoe","40.5","18.9","180","3950","male","2007"],["Adelie","Dream","39.5","16.7","178","3250","female","2007"],["Adelie","Dream","37.2","18.1","178","3900","male","2007"],["Adelie","Dream","39.5","17.8","188","3300","female","2007"],["Adelie","Dream","40.9","18.9","184","3900","male","2007"],["Adelie","Dream","36.4","17.0","195","3325","female","2007"],["Adelie","Dream","39.2","21.1","196","4150","male","2007"],["Adelie","Dream","38.8","20.0","190","3950","male","2007"],["Adelie","Dream","42.2","18.5","180","3550","female","2007"],["Adelie","Dream","37.6","19.3","181","3300","female","2007"],["Adelie","Dream","39.8","19.1","184","4650","male","2007"],["Adelie","Dream","36.5","18.0","182","3150","female","2007"],["Adelie","Dream","40.8","18.4","195","3900","male","2007"],["Adelie","Dream","36.0","18.5","186","3100","female","2007"],["Adelie","Dream","44.1","19.7","196","4400","male","2007"],["Adelie","Dream","37.0","16.9","185","3000","female","2007"],["Adelie","Dream","39.6","18.8","190","4600","male","2007"],["Adelie","Dream","41.1","19.0","182","3425","male","2007"],["Adelie","Dream","36.0","17.9","190","3450","female","2007"],["Adelie","Dream","42.3","21.2","191","4150","male","2007"],["Adelie","Biscoe","39.6","17.7","186","3500","female","2008"],["Adelie","Biscoe","40.1","18.9","188","4300","male","2008"],["Adelie","Biscoe","35.0","17.9","190","3450","female","2008"],["Adelie","Biscoe","42.0","19.5","200","4050","male","2008"],["Adelie","Biscoe","34.5","18.1","187","2900","female","2008"],["Adelie","Biscoe","41.4","18.6","191","3700","male","2008"],["Adelie","Biscoe","39.0","17.5","186","3550","female","2008"],["Adelie","Biscoe","40.6","18.8","193","3800","male","2008"],["Adelie","Biscoe","36.5","16.6","181","2850","female","2008"],["Adelie","Biscoe","37.6","19.1","194","3750","male","2008"],["Adelie","Biscoe","35.7","16.9","185","3150","female","2008"],["Adelie","Biscoe","41.3","21.1","195","4400","male","2008"],["Adelie","Biscoe","37.6","17.0","185","3600","female","2008"],["Adelie","Biscoe","41.1","18.2","192","4050","male","2008"],["Adelie","Biscoe","36.4","17.1","184","2850","female","2008"],["Adelie","Biscoe","41.6","18.0","192","3950","male","2008"],["Adelie","Biscoe","35.5","16.2","195","3350","female","2008"],["Adelie","Biscoe","41.1","19.1","188","4100","male","2008"],["Adelie","Torgersen","35.9","16.6","190","3050","female","2008"],["Adelie","Torgersen","41.8","19.4","198","4450","male","2008"],["Adelie","Torgersen","33.5","19.0","190","3600","female","2008"],["Adelie","Torgersen","39.7","18.4","190","3900","male","2008"],["Adelie","Torgersen","39.6","17.2","196","3550","female","2008"],["Adelie","Torgersen","45.8","18.9","197","4150","male","2008"],["Adelie","Torgersen","35.5","17.5","190","3700","female","2008"],["Adelie","Torgersen","42.8","18.5","195","4250","male","2008"],["Adelie","Torgersen","40.9","16.8","191","3700","female","2008"],["Adelie","Torgersen","37.2","19.4","184","3900","male","2008"],["Adelie","Torgersen","36.2","16.1","187","3550","female","2008"],["Adelie","Torgersen","42.1","19.1","195","4000","male","2008"],["Adelie","Torgersen","34.6","17.2","189","3200","female","2008"],["Adelie","Torgersen","42.9","17.6","196","4700","male","2008"],["Adelie","Torgersen","36.7","18.8","187","3800","female","2008"],["Adelie","Torgersen","35.1","19.4","193","4200","male","2008"],["Adelie","Dream","37.3","17.8","191","3350","female","2008"],["Adelie","Dream","41.3","20.3","194","3550","male","2008"],["Adelie","Dream","36.3","19.5","190","3800","male","2008"],["Adelie","Dream","36.9","18.6","189","3500","female","2008"],["Adelie","Dream","38.3","19.2","189","3950","male","2008"],["Adelie","Dream","38.9","18.8","190","3600","female","2008"],["Adelie","Dream","35.7","18.0","202","3550","female","2008"],["Adelie","Dream","41.1","18.1","205","4300","male","2008"],["Adelie","Dream","34.0","17.1","185","3400","female","2008"],["Adelie","Dream","39.6","18.1","186","4450","male","2008"],["Adelie","Dream","36.2","17.3","187","3300","female","2008"],["Adelie","Dream","40.8","18.9","208","4300","male","2008"],["Adelie","Dream","38.1","18.6","190","3700","female","2008"],["Adelie","Dream","40.3","18.5","196","4350","male","2008"],["Adelie","Dream","33.1","16.1","178","2900","female","2008"],["Adelie","Dream","43.2","18.5","192","4100","male","2008"],["Adelie","Biscoe","35.0","17.9","192","3725","female","2009"],["Adelie","Biscoe","41.0","20.0","203","4725","male","2009"],["Adelie","Biscoe","37.7","16.0","183","3075","female","2009"],["Adelie","Biscoe","37.8","20.0","190","4250","male","2009"],["Adelie","Biscoe","37.9","18.6","193","2925","female","2009"],["Adelie","Biscoe","39.7","18.9","184","3550","male","2009"],["Adelie","Biscoe","38.6","17.2","199","3750","female","2009"],["Adelie","Biscoe","38.2","20.0","190","3900","male","2009"],["Adelie","Biscoe","38.1","17.0","181","3175","female","2009"],["Adelie","Biscoe","43.2","19.0","197","4775","male","2009"],["Adelie","Biscoe","38.1","16.5","198","3825","female","2009"],["Adelie","Biscoe","45.6","20.3","191","4600","male","2009"],["Adelie","Biscoe","39.7","17.7","193","3200","female","2009"],["Adelie","Biscoe","42.2","19.5","197","4275","male","2009"],["Adelie","Biscoe","39.6","20.7","191","3900","female","2009"],["Adelie","Biscoe","42.7","18.3","196","4075","male","2009"],["Adelie","Torgersen","38.6","17.0","188","2900","female","2009"],["Adelie","Torgersen","37.3","20.5","199","3775","male","2009"],["Adelie","Torgersen","35.7","17.0","189","3350","female","2009"],["Adelie","Torgersen","41.1","18.6","189","3325","male","2009"],["Adelie","Torgersen","36.2","17.2","187","3150","female","2009"],["Adelie","Torgersen","37.7","19.8","198","3500","male","2009"],["Adelie","Torgersen","40.2","17.0","176","3450","female","2009"],["Adelie","Torgersen","41.4","18.5","202","3875","male","2009"],["Adelie","Torgersen","35.2","15.9","186","3050","female","2009"],["Adelie","Torgersen","40.6","19.0","199","4000","male","2009"],["Adelie","Torgersen","38.8","17.6","191","3275","female","2009"],["Adelie","Torgersen","41.5","18.3","195","4300","male","2009"],["Adelie","Torgersen","39.0","17.1","191","3050","female","2009"],["Adelie","Torgersen","44.1","18.0","210","4000","male","2009"],["Adelie","Torgersen","38.5","17.9","190","3325","female","2009"],["Adelie","Torgersen","43.1","19.2","197","3500","male","2009"],["Adelie","Dream","36.8","18.5","193","3500","female","2009"],["Adelie","Dream","37.5","18.5","199","4475","male","2009"],["Adelie","Dream","38.1","17.6","187","3425","female","2009"],["Adelie","Dream","41.1","17.5","190","3900","male","2009"],["Adelie","Dream","35.6","17.5","191","3175","female","2009"],["Adelie","Dream","40.2","20.1","200","3975","male","2009"],["Adelie","Dream","37.0","16.5","185","3400","female","2009"],["Adelie","Dream","39.7","17.9","193","4250","male","2009"],["Adelie","Dream","40.2","17.1","193","3400","female","2009"],["Adelie","Dream","40.6","17.2","187","3475","male","2009"],["Adelie","Dream","32.1","15.5","188","3050","female","2009"],["Adelie","Dream","40.7","17.0","190","3725","male","2009"],["Adelie","Dream","37.3","16.8","192","3000","female","2009"],["Adelie","Dream","39.0","18.7","185","3650","male","2009"],["Adelie","Dream","39.2","18.6","190","4250","male","2009"],["Adelie","Dream","36.6","18.4","184","3475","female","2009"],["Adelie","Dream","36.0","17.8","195","3450","female","2009"],["Adelie","Dream","37.8","18.1","193","3750","male","2009"],["Adelie","Dream","36.0","17.1","187","3700","female","2009"],["Adelie","Dream","41.5","18.5","201","4000","male","2009"],["Gentoo","Biscoe","46.1","13.2","211","4500","female","2007"],["Gentoo","Biscoe","50.0","16.3","230","5700","male","2007"],["Gentoo","Biscoe","48.7","14.1","210","4450","female","2007"],["Gentoo","Biscoe","50.0","15.2","218","5700","male","2007"],["Gentoo","Biscoe","47.6","14.5","215","5400","male","2007"],["Gentoo","Biscoe","46.5","13.5","210","4550","female","2007"],["Gentoo","Biscoe","45.4","14.6","211","4800","female","2007"],["Gentoo","Biscoe","46.7","15.3","219","5200","male","2007"],["Gentoo","Biscoe","43.3","13.4","209","4400","female","2007"],["Gentoo","Biscoe","46.8","15.4","215","5150","male","2007"],["Gentoo","Biscoe","40.9","13.7","214","4650","female","2007"],["Gentoo","Biscoe","49.0","16.1","216","5550","male","2007"],["Gentoo","Biscoe","45.5","13.7","214","4650","female","2007"],["Gentoo","Biscoe","48.4","14.6","213","5850","male","2007"],["Gentoo","Biscoe","45.8","14.6","210","4200","female","2007"],["Gentoo","Biscoe","49.3","15.7","217","5850","male","2007"],["Gentoo","Biscoe","42.0","13.5","210","4150","female","2007"],["Gentoo","Biscoe","49.2","15.2","221","6300","male","2007"],["Gentoo","Biscoe","46.2","14.5","209","4800","female","2007"],["Gentoo","Biscoe","48.7","15.1","222","5350","male","2007"],["Gentoo","Biscoe","50.2","14.3","218","5700","male","2007"],["Gentoo","Biscoe","45.1","14.5","215","5000","female","2007"],["Gentoo","Biscoe","46.5","14.5","213","4400","female","2007"],["Gentoo","Biscoe","46.3","15.8","215","5050","male","2007"],["Gentoo","Biscoe","42.9","13.1","215","5000","female","2007"],["Gentoo","Biscoe","46.1","15.1","215","5100","male","2007"],["Gentoo","Biscoe","47.8","15.0","215","5650","male","2007"],["Gentoo","Biscoe","48.2","14.3","210","4600","female","2007"],["Gentoo","Biscoe","50.0","15.3","220","5550","male","2007"],["Gentoo","Biscoe","47.3","15.3","222","5250","male","2007"],["Gentoo","Biscoe","42.8","14.2","209","4700","female","2007"],["Gentoo","Biscoe","45.1","14.5","207","5050","female","2007"],["Gentoo","Biscoe","59.6","17.0","230","6050","male","2007"],["Gentoo","Biscoe","49.1","14.8","220","5150","female","2008"],["Gentoo","Biscoe","48.4","16.3","220","5400","male","2008"],["Gentoo","Biscoe","42.6","13.7","213","4950","female","2008"],["Gentoo","Biscoe","44.4","17.3","219","5250","male","2008"],["Gentoo","Biscoe","44.0","13.6","208","4350","female","2008"],["Gentoo","Biscoe","48.7","15.7","208","5350","male","2008"],["Gentoo","Biscoe","42.7","13.7","208","3950","female","2008"],["Gentoo","Biscoe","49.6","16.0","225","5700","male","2008"],["Gentoo","Biscoe","45.3","13.7","210","4300","female","2008"],["Gentoo","Biscoe","49.6","15.0","216","4750","male","2008"],["Gentoo","Biscoe","50.5","15.9","222","5550","male","2008"],["Gentoo","Biscoe","43.6","13.9","217","4900","female","2008"],["Gentoo","Biscoe","45.5","13.9","210","4200","female","2008"],["Gentoo","Biscoe","50.5","15.9","225","5400","male","2008"],["Gentoo","Biscoe","44.9","13.3","213","5100","female","2008"],["Gentoo","Biscoe","45.2","15.8","215","5300","male","2008"],["Gentoo","Biscoe","46.6","14.2","210","4850","female","2008"],["Gentoo","Biscoe","48.5","14.1","220","5300","male","2008"],["Gentoo","Biscoe","45.1","14.4","210","4400","female","2008"],["Gentoo","Biscoe","50.1","15.0","225","5000","male","2008"],["Gentoo","Biscoe","46.5","14.4","217","4900","female","2008"],["Gentoo","Biscoe","45.0","15.4","220","5050","male","2008"],["Gentoo","Biscoe","43.8","13.9","208","4300","female","2008"],["Gentoo","Biscoe","45.5","15.0","220","5000","male","2008"],["Gentoo","Biscoe","43.2","14.5","208","4450","female","2008"],["Gentoo","Biscoe","50.4","15.3","224","5550","male","2008"],["Gentoo","Biscoe","45.3","13.8","208","4200","female","2008"],["Gentoo","Biscoe","46.2","14.9","221","5300","male","2008"],["Gentoo","Biscoe","45.7","13.9","214","4400","female","2008"],["Gentoo","Biscoe","54.3","15.7","231","5650","male","2008"],["Gentoo","Biscoe","45.8","14.2","219","4700","female","2008"],["Gentoo","Biscoe","49.8","16.8","230","5700","male","2008"],["Gentoo","Biscoe","49.5","16.2","229","5800","male","2008"],["Gentoo","Biscoe","43.5","14.2","220","4700","female","2008"],["Gentoo","Biscoe","50.7","15.0","223","5550","male","2008"],["Gentoo","Biscoe","47.7","15.0","216","4750","female","2008"],["Gentoo","Biscoe","46.4","15.6","221","5000","male","2008"],["Gentoo","Biscoe","48.2","15.6","221","5100","male","2008"],["Gentoo","Biscoe","46.5","14.8","217","5200","female","2008"],["Gentoo","Biscoe","46.4","15.0","216","4700","female","2008"],["Gentoo","Biscoe","48.6","16.0","230","5800","male","2008"],["Gentoo","Biscoe","47.5","14.2","209","4600","female","2008"],["Gentoo","Biscoe","51.1","16.3","220","6000","male","2008"],["Gentoo","Biscoe","45.2","13.8","215","4750","female","2008"],["Gentoo","Biscoe","45.2","16.4","223","5950","male","2008"],["Gentoo","Biscoe","49.1","14.5","212","4625","female","2009"],["Gentoo","Biscoe","52.5","15.6","221","5450","male","2009"],["Gentoo","Biscoe","47.4","14.6","212","4725","female","2009"],["Gentoo","Biscoe","50.0","15.9","224","5350","male","2009"],["Gentoo","Biscoe","44.9","13.8","212","4750","female","2009"],["Gentoo","Biscoe","50.8","17.3","228","5600","male","2009"],["Gentoo","Biscoe","43.4","14.4","218","4600","female","2009"],["Gentoo","Biscoe","51.3","14.2","218","5300","male","2009"],["Gentoo","Biscoe","47.5","14.0","212","4875","female","2009"],["Gentoo","Biscoe","52.1","17.0","230","5550","male","2009"],["Gentoo","Biscoe","47.5","15.0","218","4950","female","2009"],["Gentoo","Biscoe","52.2","17.1","228","5400","male","2009"],["Gentoo","Biscoe","45.5","14.5","212","4750","female","2009"],["Gentoo","Biscoe","49.5","16.1","224","5650","male","2009"],["Gentoo","Biscoe","44.5","14.7","214","4850","female","2009"],["Gentoo","Biscoe","50.8","15.7","226","5200","male","2009"],["Gentoo","Biscoe","49.4","15.8","216","4925","male","2009"],["Gentoo","Biscoe","46.9","14.6","222","4875","female","2009"],["Gentoo","Biscoe","48.4","14.4","203","4625","female","2009"],["Gentoo","Biscoe","51.1","16.5","225","5250","male","2009"],["Gentoo","Biscoe","48.5","15.0","219","4850","female","2009"],["Gentoo","Biscoe","55.9","17.0","228","5600","male","2009"],["Gentoo","Biscoe","47.2","15.5","215","4975","female","2009"],["Gentoo","Biscoe","49.1","15.0","228","5500","male","2009"],["Gentoo","Biscoe","46.8","16.1","215","5500","male","2009"],["Gentoo","Biscoe","41.7","14.7","210","4700","female","2009"],["Gentoo","Biscoe","53.4","15.8","219","5500","male","2009"],["Gentoo","Biscoe","43.3","14.0","208","4575","female","2009"],["Gentoo","Biscoe","48.1","15.1","209","5500","male","2009"],["Gentoo","Biscoe","50.5","15.2","216","5000","female","2009"],["Gentoo","Biscoe","49.8","15.9","229","5950","male","2009"],["Gentoo","Biscoe","43.5","15.2","213","4650","female","2009"],["Gentoo","Biscoe","51.5","16.3","230","5500","male","2009"],["Gentoo","Biscoe","46.2","14.1","217","4375","female","2009"],["Gentoo","Biscoe","55.1","16.0","230","5850","male","2009"],["Gentoo","Biscoe","48.8","16.2","222","6000","male","2009"],["Gentoo","Biscoe","47.2","13.7","214","4925","female","2009"],["Gentoo","Biscoe","46.8","14.3","215","4850","female","2009"],["Gentoo","Biscoe","50.4","15.7","222","5750","male","2009"],["Gentoo","Biscoe","45.2","14.8","212","5200","female","2009"],["Gentoo","Biscoe","49.9","16.1","213","5400","male","2009"],["Chinstrap","Dream","46.5","17.9","192","3500","female","2007"],["Chinstrap","Dream","50.0","19.5","196","3900","male","2007"],["Chinstrap","Dream","51.3","19.2","193","3650","male","2007"],["Chinstrap","Dream","45.4","18.7","188","3525","female","2007"],["Chinstrap","Dream","52.7","19.8","197","3725","male","2007"],["Chinstrap","Dream","45.2","17.8","198","3950","female","2007"],["Chinstrap","Dream","46.1","18.2","178","3250","female","2007"],["Chinstrap","Dream","51.3","18.2","197","3750","male","2007"],["Chinstrap","Dream","46.0","18.9","195","4150","female","2007"],["Chinstrap","Dream","51.3","19.9","198","3700","male","2007"],["Chinstrap","Dream","46.6","17.8","193","3800","female","2007"],["Chinstrap","Dream","51.7","20.3","194","3775","male","2007"],["Chinstrap","Dream","47.0","17.3","185","3700","female","2007"],["Chinstrap","Dream","52.0","18.1","201","4050","male","2007"],["Chinstrap","Dream","45.9","17.1","190","3575","female","2007"],["Chinstrap","Dream","50.5","19.6","201","4050","male","2007"],["Chinstrap","Dream","50.3","20.0","197","3300","male","2007"],["Chinstrap","Dream","58.0","17.8","181","3700","female","2007"],["Chinstrap","Dream","46.4","18.6","190","3450","female","2007"],["Chinstrap","Dream","49.2","18.2","195","4400","male","2007"],["Chinstrap","Dream","42.4","17.3","181","3600","female","2007"],["Chinstrap","Dream","48.5","17.5","191","3400","male","2007"],["Chinstrap","Dream","43.2","16.6","187","2900","female","2007"],["Chinstrap","Dream","50.6","19.4","193","3800","male","2007"],["Chinstrap","Dream","46.7","17.9","195","3300","female","2007"],["Chinstrap","Dream","52.0","19.0","197","4150","male","2007"],["Chinstrap","Dream","50.5","18.4","200","3400","female","2008"],["Chinstrap","Dream","49.5","19.0","200","3800","male","2008"],["Chinstrap","Dream","46.4","17.8","191","3700","female","2008"],["Chinstrap","Dream","52.8","20.0","205","4550","male","2008"],["Chinstrap","Dream","40.9","16.6","187","3200","female","2008"],["Chinstrap","Dream","54.2","20.8","201","4300","male","2008"],["Chinstrap","Dream","42.5","16.7","187","3350","female","2008"],["Chinstrap","Dream","51.0","18.8","203","4100","male","2008"],["Chinstrap","Dream","49.7","18.6","195","3600","male","2008"],["Chinstrap","Dream","47.5","16.8","199","3900","female","2008"],["Chinstrap","Dream","47.6","18.3","195","3850","female","2008"],["Chinstrap","Dream","52.0","20.7","210","4800","male","2008"],["Chinstrap","Dream","46.9","16.6","192","2700","female","2008"],["Chinstrap","Dream","53.5","19.9","205","4500","male","2008"],["Chinstrap","Dream","49.0","19.5","210","3950","male","2008"],["Chinstrap","Dream","46.2","17.5","187","3650","female","2008"],["Chinstrap","Dream","50.9","19.1","196","3550","male","2008"],["Chinstrap","Dream","45.5","17.0","196","3500","female","2008"],["Chinstrap","Dream","50.9","17.9","196","3675","female","2009"],["Chinstrap","Dream","50.8","18.5","201","4450","male","2009"],["Chinstrap","Dream","50.1","17.9","190","3400","female","2009"],["Chinstrap","Dream","49.0","19.6","212","4300","male","2009"],["Chinstrap","Dream","51.5","18.7","187","3250","male","2009"],["Chinstrap","Dream","49.8","17.3","198","3675","female","2009"],["Chinstrap","Dream","48.1","16.4","199","3325","female","2009"],["Chinstrap","Dream","51.4","19.0","201","3950","male","2009"],["Chinstrap","Dream","45.7","17.3","193","3600","female","2009"],["Chinstrap","Dream","50.7","19.7","203","4050","male","2009"],["Chinstrap","Dream","42.5","17.3","187","3350","female","2009"],["Chinstrap","Dream","52.2","18.8","197","3450","male","2009"],["Chinstrap","Dream","45.2","16.6","191","3250","female","2009"],["Chinstrap","Dream","49.3","19.9","203","4050","male","2009"],["Chinstrap","Dream","50.2","18.8","202","3800","male","2009"],["Chinstrap","Dream","45.6","19.4","194","3525","female","2009"],["Chinstrap","Dream","51.9","19.5","206","3950","male","2009"],["Chinstrap","Dream","46.8","16.5","189","3650","female","2009"],["Chinstrap","Dream","45.7","17.0","195","3650","female","2009"],["Chinstrap","Dream","55.8","19.8","207","4000","male","2009"],["Chinstrap","Dream","43.5","18.1","202","3400","female","2009"],["Chinstrap","Dream","49.6","18.2","193","3775","male","2009"],["Chinstrap","Dream","50.8","19.0","210","4100","male","2009"],["Chinstrap","Dream","50.2","18.7","198","3775","female","2009"]]},"x":null,"z":null},"config":{"graphType":"Scatter2D","isR":true,"xAxis":["flipper_length_mm"],"yAxis":["body_mass_g"],"colorBy":"species","title":"Palmer penguins — flipper length vs body mass"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>Inside <code>plot_with_settings</code>, that interactivity sits in the usual card, with the resize and download controls you already use:</p>
<div class="quarto-figure quarto-figure-center">
<figure class="figure">
<p><img src="https://neuhausi.github.io/canvasxpress-blog/posts/r/interactive-figures-in-teal/penguins-demo.gif" class="img-fluid figure-img"></p>
<figcaption>Three canvasXpress plots inside plot_with_settings — select an element, open the customizer, download as HTML.</figcaption>
</figure>
</div>
</section>
<section id="describe-the-chart-instead-of-configuring-it" class="level2">
<h2 class="anchored" data-anchor-id="describe-the-chart-instead-of-configuring-it">Describe the chart instead of configuring it</h2>
<p>Because the render path is generic, you inherit whatever the widget can do. canvasXpress, for instance, can build a chart from a plain-English prompt — no <code>graphType</code>, no axes:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">plot_with_settings_srv</span>(</span>
<span id="cb3-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p"</span>,</span>
<span id="cb3-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">plot_r =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reactive</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">canvasXpress</span>(</span>
<span id="cb3-4">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data   =</span> pg,</span>
<span id="cb3-5">    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">prompt =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Create a scatter plot of bill_depth_mm vs body_mass_g and color by species"</span></span>
<span id="cb3-6">  ))</span>
<span id="cb3-7">)</span></code></pre></div>
</div>
</section>
<section id="try-it-live" class="level2">
<h2 class="anchored" data-anchor-id="try-it-live">Try it live</h2>
<p>There’s a running demo — three canvasXpress plots inside <code>plot_with_settings</code> cards:</p>
<p><a href="https://canvasxpress.shinyapps.io/teal-canvasxpress-demo/"><strong>canvasxpress.shinyapps.io/teal-canvasxpress-demo</strong></a></p>
<p>or install the PR build and run it yourself:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">pak<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">::</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pak</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pharmaverse/teal.widgets#371"</span>)</span></code></pre></div>
</div>
</section>
<section id="why-it-matters" class="level2">
<h2 class="anchored" data-anchor-id="why-it-matters">Why it matters</h2>
<p>Interactive dashboards usually mean leaving the tools you trust for a BI platform, and losing reproducibility in the trade. This keeps both: the module model and reproducible, code-defined figures of teal, plus the interactivity and portability of an htmlwidget. The figure is still code — it just moves now.</p>
<p>The discussion that started it is <a href="https://github.com/pharmaverse/teal/discussions/1757">teal#1757</a>; the PR is <a href="https://github.com/pharmaverse/teal.widgets/pull/371">teal.widgets#371</a>. Feedback from teal users is welcome, especially on how you’d want widget support wired into the module API.</p>


</section>

 ]]></description>
  <category>R</category>
  <category>canvasXpress</category>
  <category>shiny</category>
  <category>teal</category>
  <category>pharmaverse</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/r/interactive-figures-in-teal/</guid>
  <pubDate>Fri, 06 Nov 2026 05:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/r/interactive-figures-in-teal/thumbnail.png" medium="image" type="image/png" height="133" width="144"/>
</item>
<item>
  <title>Interactive network graphs in JavaScript with CanvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/js/network-graphs-in-javascript/</link>
  <description><![CDATA[ 




<p>A network graph shows <strong>relationships</strong>: nodes connected by edges, laid out so connected things sit near each other. In the browser the common answer is to hand-roll a force simulation in D3 — a few hundred lines. CanvasXpress is a JavaScript library at heart, so the whole thing is a <code>data</code> object of nodes and edges plus a <code>config</code>.</p>
<section id="load-the-library" class="level2">
<h2 class="anchored" data-anchor-id="load-the-library">Load the library</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb1-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">link</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> href</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> rel</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"stylesheet"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> src</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="the-markup-and-the-spec" class="level2">
<h2 class="anchored" data-anchor-id="the-markup-and-the-spec">The markup and the spec</h2>
<p>Nodes carry <code>id</code>, <code>name</code>, <code>group</code>; edges carry <code>id1</code>, <code>id2</code>, <code>value</code>. <code>colorNodeBy</code> colours by community and <code>networkLayoutType: "forceDirected"</code> runs the physics.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb2-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"network"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"650"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"500"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alpha"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Beta"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gamma"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> nodes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> byGroup <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-4">  groups<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">forEach</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (g) {</span>
<span id="cb2-5">    byGroup[g] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-6">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>) {</span>
<span id="cb2-7">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> nid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> k<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> nodes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>({ <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> nid<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">name</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> g <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">group</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> g })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-8">      byGroup[g]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(nid)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> k<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++;</span></span>
<span id="cb2-9">    }</span>
<span id="cb2-10">  })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-11"></span>
<span id="cb2-12">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> edges <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-13">  groups<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">forEach</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (g) {                         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// dense within a community</span></span>
<span id="cb2-14">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> byGroup[g]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>)</span>
<span id="cb2-16">      <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> j<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>)</span>
<span id="cb2-17">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>)</span>
<span id="cb2-18">          edges<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>({ <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">id1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> m[i]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">id2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> m[j]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">value</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">floor</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>) })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-19">  })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-20">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> e <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> e <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> e<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>) {                         <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// a few cross-community links</span></span>
<span id="cb2-21">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> pair <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> groups<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">slice</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sort</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> () { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">slice</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-22">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> byGroup[pair[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> byGroup[pair[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-23">    edges<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>({ <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">id1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> a[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">floor</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span>)]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-24">                 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">id2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> b[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">floor</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> b<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span>)]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">value</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-25">  }</span>
<span id="cb2-26"></span>
<span id="cb2-27">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb2-28">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Network"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-29">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">networkLayoutType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"forceDirected"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-30">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">colorNodeBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-31">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">nodeSize</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-32">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">showAnimation</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-33">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A small community network"</span></span>
<span id="cb2-34">  }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-35"></span>
<span id="cb2-36">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CanvasXpress</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"network"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">nodes</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> nodes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">edges</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> edges }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> config)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-37"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="live-result" class="level2">
<h2 class="anchored" data-anchor-id="live-result">Live result</h2>
<link href="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"></script>
<canvas id="networkLive" width="650" height="500"></canvas>
<script>
(function () {
  function draw() {
    if (typeof CanvasXpress === "undefined") { return setTimeout(draw, 60); }
    var groups = ["Alpha", "Beta", "Gamma"], nodes = [], byGroup = {}, k = 0;
    groups.forEach(function (g) {
      byGroup[g] = [];
      for (var i = 0; i < 7; i++) {
        var nid = "n" + k; nodes.push({ id: nid, name: g + (i + 1), group: g });
        byGroup[g].push(nid); k++;
      }
    });
    var edges = [];
    groups.forEach(function (g) {
      var m = byGroup[g];
      for (var i = 0; i < m.length; i++)
        for (var j = i + 1; j < m.length; j++)
          if (Math.random() < 0.5)
            edges.push({ id1: m[i], id2: m[j], value: 1 + Math.floor(Math.random() * 5) });
    });
    for (var e = 0; e < 6; e++) {
      var pair = groups.slice().sort(function () { return Math.random() - 0.5; }).slice(0, 2);
      var a = byGroup[pair[0]], b = byGroup[pair[1]];
      edges.push({ id1: a[Math.floor(Math.random() * a.length)],
                   id2: b[Math.floor(Math.random() * b.length)], value: 1 });
    }
    new CanvasXpress("networkLive", { nodes: nodes, edges: edges },
      { graphType: "Network", networkLayoutType: "forceDirected", colorNodeBy: "group",
        nodeSize: 25, showAnimation: true, title: "A small community network" });
  }
  draw();
})();
</script>
<p>Drag any node and the layout settles around it; hover to read the label. The three communities separate on their own because within-group edges outnumber the cross-group ones.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The nodes, edges and <code>config</code> <strong>are</strong> the figure — one portable JSON spec that renders the same from R, Python, or a web page.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../sankey-diagrams-in-javascript/">Sankey / alluvial diagrams in JavaScript</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Source &amp; npm: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>JavaScript</category>
  <category>CanvasXpress</category>
  <category>network</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/js/network-graphs-in-javascript/</guid>
  <pubDate>Sat, 31 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/js/network-graphs-in-javascript/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>Genome browser tracks in JavaScript with CanvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/js/genome-tracks-in-javascript/</link>
  <description><![CDATA[ 




<p>A genome browser view stacks <strong>tracks</strong> that share one coordinate axis: coverage, gene models, variants. Building one in the browser by hand is a lot of SVG and coordinate math. CanvasXpress is a JavaScript library at heart, so the whole view is a <code>data</code> object of tracks plus a <code>config</code>.</p>
<section id="load-the-library" class="level2">
<h2 class="anchored" data-anchor-id="load-the-library">Load the library</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb1-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">link</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> href</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> rel</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"stylesheet"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> src</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="the-markup-and-the-spec" class="level2">
<h2 class="anchored" data-anchor-id="the-markup-and-the-spec">The markup and the spec</h2>
<p>Four tracks that share one coordinate axis: <strong>gene models</strong> (<code>box</code>, multi-exon, connected), <strong>coverage across three tissues</strong> (<code>bar</code>), an <strong>expression heatmap</strong> (<code>heatmap</code>), and <strong>variant markers</strong> (<code>triangle</code>).</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb2-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genome"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"760"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"520"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-3">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Gene models: each gene is a set of exon [start, end] intervals, drawn connected.</span></span>
<span id="cb2-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> genes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-5">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> j<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>) {</span>
<span id="cb2-6">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">120</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> nex <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">floor</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> exons <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-7">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> nex<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> k<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>) exons<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>([start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-8">    genes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>({ <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GENE"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">dir</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">===</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">?</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"right"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"left"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-9">                 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">fill</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(70,130,220)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">outline</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(0,0,0)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> exons })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-10">  }</span>
<span id="cb2-11"></span>
<span id="cb2-12">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Coverage and expression: one entry per binned position, three tissues each.</span></span>
<span id="cb2-13">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> coverage <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> express <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> rnd <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> b) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">floor</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-14">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">22</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>) {</span>
<span id="cb2-15">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> o <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">22</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-16">    coverage<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>({ <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">offset</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> o<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnd</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnd</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnd</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>)] })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-17">    express<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>({ <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">offset</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> o<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-18">                   <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-19">                          <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)] })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-20">  }</span>
<span id="cb2-21"></span>
<span id="cb2-22">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Variants: point markers at genomic positions.</span></span>
<span id="cb2-23">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> snps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-24">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>)</span>
<span id="cb2-25">    snps<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>({ <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rs"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> s)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">offset</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnd</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">520</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">fill</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(200,40,40)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">outline</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(0,0,0)"</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-26"></span>
<span id="cb2-27">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">tracks</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [</span>
<span id="cb2-28">    { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">name</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genes (exon models)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"box"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">connect</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> genes }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-29">    { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">name</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Coverage — Heart / Liver / Kidney"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bar"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">120</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-30">      <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">fill</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(80,80,200)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">outline</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(60,60,60)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> coverage }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-31">    { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">name</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expression (z-score)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"heatmap"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">90</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> express }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-32">    { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">name</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SNPs"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">type</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"triangle"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> snps }</span>
<span id="cb2-33">  ]}<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-34"></span>
<span id="cb2-35">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genome"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">background</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(245,245,245)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">featureStaggered</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-36">                 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Multi-track genome browser: genes, coverage, expression and variants"</span> }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-37"></span>
<span id="cb2-38">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CanvasXpress</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genome"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> config)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-39"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="live-result" class="level2">
<h2 class="anchored" data-anchor-id="live-result">Live result</h2>
<link href="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"></script>
<canvas id="genomeLive" width="760" height="520"></canvas>
<script>
(function () {
  function draw() {
    if (typeof CanvasXpress === "undefined") { return setTimeout(draw, 60); }
    var rnd = function (a, b) { return a + Math.floor(Math.random() * (b - a + 1)); };
    var genes = [];
    for (var j = 0; j < 4; j++) {
      var start = 40 + j * 120, nex = 2 + Math.floor(Math.random() * 3), exons = [];
      for (var k = 0; k < nex; k++) exons.push([start + k * 30, start + k * 30 + 18]);
      genes.push({ id: "GENE" + (j + 1), dir: j % 2 === 0 ? "right" : "left",
                   fill: "rgb(70,130,220)", outline: "rgb(0,0,0)", data: exons });
    }
    var coverage = [], express = [];
    for (var i = 0; i < 22; i++) {
      var o = 50 + i * 22;
      coverage.push({ id: "p" + i, offset: o, data: [rnd(8, 45), rnd(8, 45), rnd(8, 45)] });
      express.push({ id: "p" + i, offset: o,
                     data: [Math.round(Math.random() * 4 - 2), Math.round(Math.random() * 4 - 2),
                            Math.round(Math.random() * 4 - 2)] });
    }
    var snps = [];
    for (var s = 0; s < 9; s++)
      snps.push({ id: "rs" + (1000 + s), offset: rnd(45, 520), fill: "rgb(200,40,40)", outline: "rgb(0,0,0)" });
    new CanvasXpress("genomeLive",
      { tracks: [
        { name: "Genes (exon models)", type: "box", connect: true, data: genes },
        { name: "Coverage — Heart / Liver / Kidney", type: "bar", height: 120,
          fill: "rgb(80,80,200)", outline: "rgb(60,60,60)", data: coverage },
        { name: "Expression (z-score)", type: "heatmap", height: 90, data: express },
        { name: "SNPs", type: "triangle", data: snps } ] },
      { graphType: "Genome", background: "rgb(245,245,245)", featureStaggered: true,
        title: "Multi-track genome browser: genes, coverage, expression and variants" });
  }
  draw();
})();
</script>
<p>Scroll/drag to pan and zoom into a region; every track stays locked to the shared coordinate axis, so the gene models, coverage, expression and variants line up position-for-position. Swap each track for your own pileup, annotation and VCF-derived data.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The tracks and <code>config</code> <strong>are</strong> the figure — one portable JSON spec that renders the same from R, Python, or a web page.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../network-graphs-in-javascript/">Interactive network graphs in JavaScript</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Source &amp; npm: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>JavaScript</category>
  <category>CanvasXpress</category>
  <category>genome</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/js/genome-tracks-in-javascript/</guid>
  <pubDate>Sat, 31 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/js/genome-tracks-in-javascript/thumbnail.png" medium="image" type="image/png" height="272" width="144"/>
</item>
<item>
  <title>An interactive NGS sequencing-QC dashboard in JavaScript with CanvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/js/linked-dashboards-in-javascript/</link>
  <description><![CDATA[ 




<p>After a sequencing run you get a QC table — one row per sample, a dozen metrics — and you need to answer three questions fast: <strong>which samples fail, is a whole batch off, and are the failures correlated?</strong> A single scatter can’t do it; you want several views that <strong>talk to each other</strong> — select a suspicious sample in one and see it light up in the rest. In the browser that usually means wiring event handlers between chart libraries by hand. CanvasXpress does it for you: give every panel the same <strong>broadcast group</strong> and a selection broadcasts to all of them. Here we build a real QC dashboard for 96 RNA/exome samples.</p>
<section id="load-the-library-and-the-data" class="level2">
<h2 class="anchored" data-anchor-id="load-the-library-and-the-data">Load the library and the data</h2>
<p>The 96-sample QC table is published next to this post as a small JS object, <a href="qc-data.js"><code>qc-data.js</code></a> — <code>QC_DATA</code> is a sample-centric CanvasXpress <code>data</code> object (each sample is a point; <code>z</code> holds its lane/batch/library).</p>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb1-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">link</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> href</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> rel</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"stylesheet"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> src</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-3"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> src</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qc-data.js"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="the-panels" class="level2">
<h2 class="anchored" data-anchor-id="the-panels">The panels</h2>
<p>The overview heatmap transposes the data to metrics × samples and z-scores each metric. The four triage panels read <code>QC_DATA</code> directly and all share <code>broadcastGroup: "qc"</code> — select points in one and the same samples re-mark in the rest.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb2-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcHeat"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"820"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"420"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcMap"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"640"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"360"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-3"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcContam"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"640"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"360"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-4"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcQ30"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"640"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"360"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-5"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcReads"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"820"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"300"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-6"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-7">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> QC_DATA<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">smps</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> samples <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> QC_DATA<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">vars</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> QC_DATA<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-8"></span>
<span id="cb2-9">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Overview: transpose to metrics x samples and z-score each metric.</span></span>
<span id="cb2-10">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> hmData <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (_<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> c) {</span>
<span id="cb2-11">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> col <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> rows<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (r) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> r[c]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-12">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> mean <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reduce</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> b) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> b<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-13">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> sd <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sqrt</span>(col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">reduce</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> b) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> a <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> mean) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> mean)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">||</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-14">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (v) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>((v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> mean) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> sd <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-15">  })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-16">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CanvasXpress</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcHeat"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-17">    { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">y</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">vars</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> metrics<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">smps</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> samples<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> hmData }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-18">      <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">x</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Batch</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> QC_DATA<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">z</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Batch</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Library</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> QC_DATA<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">z</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Library</span> } }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-19">    { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heatmap"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">samplesClustered</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">variablesClustered</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-20">      <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">colorSpectrum</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"navy"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"firebrick3"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-21">      <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"QC metrics (z-scored) — 96 samples clustered"</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-22"></span>
<span id="cb2-23">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// Linked triage panels (same QC_DATA, shared broadcast group).</span></span>
<span id="cb2-24">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">panel</span>(id<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> cfg) {</span>
<span id="cb2-25">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CanvasXpress</span>(id<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> QC_DATA<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Object</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">assign</span>({ <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">broadcast</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">true</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">broadcastGroup</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qc"</span> }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> cfg))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-26">  }</span>
<span id="cb2-27">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">panel</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcMap"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">xAxis</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_duplication"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">yAxis</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_mapped"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-28">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">colorBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">sizeBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total_reads"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mapping rate vs duplication — select bottom-right"</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-29">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">panel</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcContam"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">xAxis</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_mapped"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">yAxis</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"contamination_freemix"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-30">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">colorBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Contamination (freemix) vs mapping rate"</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-31">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">panel</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcQ30"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">xAxis</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gc_content"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">yAxis</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_q30"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-32">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">colorBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Library"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Q30 vs GC content, coloured by library"</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-33">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">panel</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcReads"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bar"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphOrientation</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vertical"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">xAxis</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total_reads"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-34">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">colorBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Total reads per sample (flag the short ones)"</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-35"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="live-result" class="level2">
<h2 class="anchored" data-anchor-id="live-result">Live result</h2>
<p>Drag a selection box across the bad cluster in the mapping-vs-duplication panel — the other panels restrict to the same samples so you can read their contamination, library and depth.</p>
<link href="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"></script>
<script src="qc-data.js"></script>
<canvas id="qcHeatLive" width="820" height="420"></canvas>
<canvas id="qcMapLive" width="640" height="360"></canvas>
<canvas id="qcContamLive" width="640" height="360"></canvas>
<canvas id="qcQ30Live" width="640" height="360"></canvas>
<canvas id="qcReadsLive" width="820" height="300"></canvas>
<script>
(function () {
  function draw() {
    if (typeof CanvasXpress === "undefined" || typeof QC_DATA === "undefined") { return setTimeout(draw, 60); }
    var metrics = QC_DATA.y.smps, samples = QC_DATA.y.vars, rows = QC_DATA.y.data;
    var hmData = metrics.map(function (_, c) {
      var col = rows.map(function (r) { return r[c]; });
      var mean = col.reduce(function (a, b) { return a + b; }, 0) / col.length;
      var sd = Math.sqrt(col.reduce(function (a, b) { return a + (b - mean) * (b - mean); }, 0) / col.length) || 1;
      return col.map(function (v) { return Math.round((v - mean) / sd * 100) / 100; });
    });
    new CanvasXpress("qcHeatLive",
      { y: { vars: metrics, smps: samples, data: hmData },
        x: { Batch: QC_DATA.z.Batch, Library: QC_DATA.z.Library } },
      { graphType: "Heatmap", samplesClustered: true, variablesClustered: true,
        colorSpectrum: ["navy", "white", "firebrick3"],
        title: "QC metrics (z-scored) — 96 samples clustered" });
    function panel(id, cfg) {
      new CanvasXpress(id, QC_DATA, Object.assign({ broadcast: true, broadcastGroup: "qc" }, cfg));
    }
    panel("qcMapLive", { graphType: "Scatter2D", xAxis: ["pct_duplication"], yAxis: ["pct_mapped"],
      colorBy: "Batch", sizeBy: "total_reads", title: "Mapping rate vs duplication — select bottom-right" });
    panel("qcContamLive", { graphType: "Scatter2D", xAxis: ["pct_mapped"], yAxis: ["contamination_freemix"],
      colorBy: "Batch", title: "Contamination (freemix) vs mapping rate" });
    panel("qcQ30Live", { graphType: "Scatter2D", xAxis: ["gc_content"], yAxis: ["pct_q30"],
      colorBy: "Library", title: "Q30 vs GC content, coloured by library" });
    panel("qcReadsLive", { graphType: "Bar", graphOrientation: "vertical", xAxis: ["total_reads"],
      colorBy: "Batch", title: "Total reads per sample (flag the short ones)" });
  }
  draw();
})();
</script>
<p>The cross-filter is one shared <code>broadcastGroup</code> — no framework, no event wiring. Each panel stays a portable <code>data</code> + <code>config</code> spec.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The same specs reproduce the dashboard from R, Python, or a web page, against the same QC table.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../network-graphs-in-javascript/">Interactive network graphs in JavaScript</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Source &amp; npm: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>JavaScript</category>
  <category>CanvasXpress</category>
  <category>dashboard</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/js/linked-dashboards-in-javascript/</guid>
  <pubDate>Sat, 31 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/js/linked-dashboards-in-javascript/thumbnail.png" medium="image" type="image/png" height="110" width="144"/>
</item>
<item>
  <title>Interactive network graphs in Python with canvasxpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/python/network-graphs-in-python/</link>
  <description><![CDATA[ 




<p>A network graph shows <strong>relationships</strong>: nodes connected by edges, laid out so connected things sit near each other. The usual Python reach is <code>networkx</code> + matplotlib (static) or <code>pyvis</code>. Here we build one with <a href="https://pypi.org/project/canvasxpress/">canvasxpress</a> — draggable, hover-labelled, force-directed, and reproducible from a single portable spec.</p>
<section id="install" class="level2">
<h2 class="anchored" data-anchor-id="install">Install</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install canvasxpress</span></code></pre></div>
</section>
<section id="the-data-shape" class="level2">
<h2 class="anchored" data-anchor-id="the-data-shape">The data shape</h2>
<p>canvasXpress builds a network from two lists: <strong>nodes</strong> (<code>id</code>, <code>name</code>, <code>group</code>) and <strong>edges</strong> (<code>id1</code>, <code>id2</code>, <code>value</code>). Swap this simulated three-community graph for your own.</p>
<div id="d93a4a56" class="cell" data-execution_count="1">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> random</span>
<span id="cb2-2">random.seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb2-3"></span>
<span id="cb2-4">groups <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alpha"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Beta"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gamma"</span>]</span>
<span id="cb2-5">nodes, by_group <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [], {g: [] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> g <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> groups}</span>
<span id="cb2-6">k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span></span>
<span id="cb2-7"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> g <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> groups:</span>
<span id="cb2-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>):</span>
<span id="cb2-9">        nid <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"n</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>k<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> nodes.append({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>: nid, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>: <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>g<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>: g})</span>
<span id="cb2-10">        by_group[g].append(nid)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span></span>
<span id="cb2-11"></span>
<span id="cb2-12">edges <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb2-13"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> g <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> groups:                                   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># dense within a community</span></span>
<span id="cb2-14">    m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> by_group[g]</span>
<span id="cb2-15">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(m)):</span>
<span id="cb2-16">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(m)):</span>
<span id="cb2-17">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> random.random() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>:</span>
<span id="cb2-18">                edges.append({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id1"</span>: m[i], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id2"</span>: m[j], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>: random.randint(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)})</span>
<span id="cb2-19"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>):                                 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a few cross-community links</span></span>
<span id="cb2-20">    g1, g2 <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> random.sample(groups, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb2-21">    edges.append({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id1"</span>: random.choice(by_group[g1]), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id2"</span>: random.choice(by_group[g2]), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"value"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>})</span></code></pre></div>
</div>
</section>
<section id="the-plot" class="level2">
<h2 class="anchored" data-anchor-id="the-plot">The plot</h2>
<div id="499d16e7" class="cell" data-execution_count="2">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.canvas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CanvasXpress</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.render.jupyter <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CXNoteBook</span>
<span id="cb3-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> IPython.display <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> display</span>
<span id="cb3-4"></span>
<span id="cb3-5">data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nodes"</span>: nodes, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"edges"</span>: edges}</span>
<span id="cb3-6">config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb3-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Network"</span>,</span>
<span id="cb3-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"networkLayoutType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"forceDirected"</span>,</span>
<span id="cb3-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"colorNodeBy"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>,</span>
<span id="cb3-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"nodeSize"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>,</span>
<span id="cb3-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"showAnimation"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb3-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A small community network"</span>,</span>
<span id="cb3-13">}</span>
<span id="cb3-14"></span>
<span id="cb3-15">cx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CanvasXpress(render_to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"network"</span>, data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>data, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>config, width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">650</span>, height<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span>)</span>
<span id="cb3-16"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> part <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> CXNoteBook(cx).render():</span>
<span id="cb3-17">    display(part)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="network" width="650" height="500"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("network");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart network removed for re-rendering.");
  } else {
    console.log("Chart network ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart network could not be cleaned for re-rendering:", error);
}

var chart_network = new CanvasXpress({"renderTo": "network", "data": {"nodes": [{"id": "n0", "name": "Alpha1", "group": "Alpha"}, {"id": "n1", "name": "Alpha2", "group": "Alpha"}, {"id": "n2", "name": "Alpha3", "group": "Alpha"}, {"id": "n3", "name": "Alpha4", "group": "Alpha"}, {"id": "n4", "name": "Alpha5", "group": "Alpha"}, {"id": "n5", "name": "Alpha6", "group": "Alpha"}, {"id": "n6", "name": "Alpha7", "group": "Alpha"}, {"id": "n7", "name": "Beta1", "group": "Beta"}, {"id": "n8", "name": "Beta2", "group": "Beta"}, {"id": "n9", "name": "Beta3", "group": "Beta"}, {"id": "n10", "name": "Beta4", "group": "Beta"}, {"id": "n11", "name": "Beta5", "group": "Beta"}, {"id": "n12", "name": "Beta6", "group": "Beta"}, {"id": "n13", "name": "Beta7", "group": "Beta"}, {"id": "n14", "name": "Gamma1", "group": "Gamma"}, {"id": "n15", "name": "Gamma2", "group": "Gamma"}, {"id": "n16", "name": "Gamma3", "group": "Gamma"}, {"id": "n17", "name": "Gamma4", "group": "Gamma"}, {"id": "n18", "name": "Gamma5", "group": "Gamma"}, {"id": "n19", "name": "Gamma6", "group": "Gamma"}, {"id": "n20", "name": "Gamma7", "group": "Gamma"}], "edges": [{"id1": "n0", "id2": "n1", "value": 1}, {"id1": "n0", "id2": "n2", "value": 4}, {"id1": "n0", "id2": "n4", "value": 4}, {"id1": "n0", "id2": "n6", "value": 1}, {"id1": "n1", "id2": "n3", "value": 5}, {"id1": "n1", "id2": "n5", "value": 4}, {"id1": "n1", "id2": "n6", "value": 2}, {"id1": "n2", "id2": "n4", "value": 3}, {"id1": "n2", "id2": "n5", "value": 1}, {"id1": "n3", "id2": "n4", "value": 4}, {"id1": "n7", "id2": "n10", "value": 2}, {"id1": "n8", "id2": "n9", "value": 5}, {"id1": "n8", "id2": "n11", "value": 3}, {"id1": "n8", "id2": "n12", "value": 3}, {"id1": "n10", "id2": "n12", "value": 3}, {"id1": "n14", "id2": "n16", "value": 2}, {"id1": "n14", "id2": "n18", "value": 2}, {"id1": "n14", "id2": "n19", "value": 3}, {"id1": "n14", "id2": "n20", "value": 5}, {"id1": "n15", "id2": "n16", "value": 2}, {"id1": "n15", "id2": "n18", "value": 4}, {"id1": "n15", "id2": "n20", "value": 3}, {"id1": "n16", "id2": "n20", "value": 2}, {"id1": "n17", "id2": "n18", "value": 2}, {"id1": "n19", "id2": "n20", "value": 5}, {"id1": "n10", "id2": "n16", "value": 1}, {"id1": "n17", "id2": "n6", "value": 1}, {"id1": "n18", "id2": "n6", "value": 1}, {"id1": "n17", "id2": "n0", "value": 1}, {"id1": "n11", "id2": "n18", "value": 1}, {"id1": "n3", "id2": "n13", "value": 1}], "x": null, "z": null}, "config": {"graphType": "Network", "networkLayoutType": "forceDirected", "colorNodeBy": "group", "nodeSize": 25, "showAnimation": true, "title": "A small community network"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
<p>Drag any node and the layout settles around it; hover to read the label. The three communities separate on their own because within-group edges outnumber the cross-group ones.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The nodes, edges and <code>config</code> <strong>are</strong> the figure — one portable JSON spec that renders the identical network from R or JavaScript, and can be validated and re-rendered later.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../sankey-diagrams-in-python/">Sankey / alluvial diagrams in Python</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Package: <a href="https://pypi.org/project/canvasxpress/" class="uri">https://pypi.org/project/canvasxpress/</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>canvasxpress</category>
  <category>network</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/python/network-graphs-in-python/</guid>
  <pubDate>Fri, 30 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/python/network-graphs-in-python/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>An interactive NGS sequencing-QC dashboard in Python with canvasxpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/python/linked-dashboards-in-python/</link>
  <description><![CDATA[ 




<p>After a sequencing run you get a QC table — one row per sample, a dozen metrics — and you need to answer three questions fast: <strong>which samples fail, is a whole batch off, and are the failures correlated?</strong> A single scatter can’t do it; you want several views that <strong>talk to each other</strong> — select a suspicious sample in one and see it light up in the rest. In Python that usually means Dash or Streamlit (a server, callbacks). canvasXpress does it client-side: give every panel the same <strong>broadcast group</strong> and a selection broadcasts to all of them. Here we build a real QC dashboard for 96 RNA/exome samples.</p>
<section id="install" class="level2">
<h2 class="anchored" data-anchor-id="install">Install</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install canvasxpress</span></code></pre></div>
</section>
<section id="the-qc-table" class="level2">
<h2 class="anchored" data-anchor-id="the-qc-table">The QC table</h2>
<p>96 samples with mapping rate, duplication, Q30, GC, insert size and contamination (VerifyBamID <code>freemix</code>), plus lane / batch / library annotations. (Download: <a href="ngs-qc.csv"><code>ngs-qc.csv</code></a>.)</p>
<div id="1697589b" class="cell" data-execution_count="1">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> csv, statistics <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> st</span>
<span id="cb2-2"></span>
<span id="cb2-3">rows <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(csv.DictReader(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">open</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ngs-qc.csv"</span>)))</span>
<span id="cb2-4">metrics <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total_reads"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_mapped"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_duplication"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_q30"</span>,</span>
<span id="cb2-5">           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gc_content"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"insert_size"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"contamination_freemix"</span>]</span>
<span id="cb2-6"></span>
<span id="cb2-7">samples <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sample"</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> rows]</span>
<span id="cb2-8">annot   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Lane"</span>: [r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"lane"</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> rows], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span>: [r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"batch"</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> rows],</span>
<span id="cb2-9">           <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Library"</span>: [r[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"library"</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> rows]}</span>
<span id="cb2-10">raw <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {m: [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">float</span>(r[m]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> r <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> rows] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> m <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> metrics}</span>
<span id="cb2-11"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(samples), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"samples,"</span>, <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(metrics), <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"metrics"</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>96 samples, 7 metrics</code></pre>
</div>
</div>
</section>
<section id="overview-a-clustered-qc-heatmap" class="level2">
<h2 class="anchored" data-anchor-id="overview-a-clustered-qc-heatmap">Overview — a clustered QC heatmap</h2>
<p>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. Here the matrix is metrics × samples.</p>
<div id="54355646" class="cell" data-execution_count="2">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.canvas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CanvasXpress</span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.render.jupyter <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CXNoteBook</span>
<span id="cb4-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> IPython.display <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> display</span>
<span id="cb4-4"></span>
<span id="cb4-5">z <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {m: [(v <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> st.mean(raw[m])) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> (st.pstdev(raw[m]) <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">or</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> v <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> raw[m]] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> m <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> metrics}</span>
<span id="cb4-6">hm <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"y"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vars"</span>: metrics, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"smps"</span>: samples, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: [[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(x, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> x <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> z[m]] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> m <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> metrics]},</span>
<span id="cb4-7">      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span>: annot[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Library"</span>: annot[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Library"</span>]}}</span>
<span id="cb4-8"></span>
<span id="cb4-9">cx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CanvasXpress(render_to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcHeat"</span>, data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>hm, width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">820</span>, height<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">420</span>, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>{</span>
<span id="cb4-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heatmap"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"samplesClustered"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"variablesClustered"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb4-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"colorSpectrum"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"navy"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"firebrick3"</span>],</span>
<span id="cb4-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"QC metrics (z-scored) — 96 samples clustered"</span>})</span>
<span id="cb4-13"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> part <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> CXNoteBook(cx).render():</span>
<span id="cb4-14">    display(part)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="qcHeat" width="820" height="420"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("qcHeat");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart qcHeat removed for re-rendering.");
  } else {
    console.log("Chart qcHeat ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart qcHeat could not be cleaned for re-rendering:", error);
}

var chart_qcHeat = new CanvasXpress({"renderTo": "qcHeat", "data": {"y": {"vars": ["total_reads", "pct_mapped", "pct_duplication", "pct_q30", "gc_content", "insert_size", "contamination_freemix"], "smps": ["S001", "S002", "S003", "S004", "S005", "S006", "S007", "S008", "S009", "S010", "S011", "S012", "S013", "S014", "S015", "S016", "S017", "S018", "S019", "S020", "S021", "S022", "S023", "S024", "S025", "S026", "S027", "S028", "S029", "S030", "S031", "S032", "S033", "S034", "S035", "S036", "S037", "S038", "S039", "S040", "S041", "S042", "S043", "S044", "S045", "S046", "S047", "S048", "S049", "S050", "S051", "S052", "S053", "S054", "S055", "S056", "S057", "S058", "S059", "S060", "S061", "S062", "S063", "S064", "S065", "S066", "S067", "S068", "S069", "S070", "S071", "S072", "S073", "S074", "S075", "S076", "S077", "S078", "S079", "S080", "S081", "S082", "S083", "S084", "S085", "S086", "S087", "S088", "S089", "S090", "S091", "S092", "S093", "S094", "S095", "S096"], "data": [[-0.3, -0.23, -1.09, 1.27, 0.25, -0.64, 0.4, 0.61, -0.67, 0.94, -0.97, 0.69, 0.77, 0.52, 0.49, -0.09, 1.83, 0.19, 0.58, -0.63, -1.06, 1.84, 0.21, 0.88, -1.63, 1.39, 0.57, -1.77, 0.22, -1.3, 0.2, -0.56, 1.05, -0.72, 0.16, -1.95, -0.76, 1.02, -0.24, 2.18, -2.13, 0.63, -0.71, 1.05, -0.33, -0.96, 0.35, -0.35, 0.13, -1.78, 0.93, -0.18, 0.54, 0.1, -0.26, -2.22, -0.85, 1.01, 0.09, -0.92, 0.18, -1.14, -1.39, 0.51, -1.41, 0.58, -1.04, 0.91, -0.6, 0.67, -0.03, 0.66, 0.18, -1.29, -0.84, -1.34, -0.81, -0.41, 1.04, 0.72, 1.2, 0.82, 0.43, 3.01, 1.03, -1.17, -0.45, -0.6, 1.3, -0.57, 0.22, 0.95, -1.35, 0.73, 1.21, 0.25], [0.29, -1.51, 1.73, 1.18, 0.14, 0.28, 1.02, 0.65, 0.96, 1.41, -0.68, -0.6, -0.03, -0.66, 1.11, -1.68, 0.04, 0.96, -0.78, -0.75, -3.5, 1.25, -1.01, -0.54, -1.1, 0.04, 0.77, 0.69, 1.74, 0.52, -1.1, -0.35, 0.32, -0.83, -0.6, 0.34, -0.71, -0.77, 0.03, 0.37, -1.03, 0.17, 0.8, 1.18, -0.96, 0.18, 0.95, -0.29, 1.62, -1.18, 0.88, 0.42, 0.91, 0.74, 1.74, 0.66, -0.09, 0.39, 0.97, 0.07, -2.43, -0.31, 0.77, -2.7, -1.87, 1.74, 0.23, -0.06, -0.12, 0.02, -1.08, 0.19, 0.26, 0.69, -0.15, -2.81, 1.06, 0.32, -0.25, -0.22, 0.2, 0.98, -0.52, 0.5, -0.19, -0.54, 0.26, 0.03, -0.26, 0.12, 0.11, 0.36, -1.05, 0.88, -1.13, 0.19], [-0.38, -0.15, -1.0, -0.07, -0.51, -0.07, 0.81, 0.68, -0.17, 2.25, 0.09, 1.54, -0.4, -0.61, -1.37, 1.31, 0.51, -1.47, -1.68, 0.32, 1.73, -0.37, 1.4, -1.11, -1.76, -1.28, -0.63, 0.67, -1.25, 0.31, -0.58, 1.07, -0.85, 1.47, -1.55, -0.06, -0.84, -0.4, -0.51, 0.7, 0.38, 1.94, -0.83, 0.41, -0.57, -1.34, -0.44, -0.45, -0.6, 0.85, -0.38, 1.21, -0.64, 0.21, -1.21, -0.92, -1.26, 1.01, -0.42, -1.5, 1.3, 0.59, -0.31, 2.58, 2.62, -0.88, 0.13, 0.16, -1.03, 1.26, -0.27, -1.14, -0.55, 0.94, -0.33, 1.08, -0.54, -0.34, 0.91, 0.11, -0.97, 0.05, -0.07, 0.19, -1.58, 0.77, -1.29, 0.84, -0.37, 0.72, 0.9, 1.8, 1.16, 0.1, 0.13, 0.09], [-1.13, 1.28, -0.58, 0.56, -0.09, -0.2, -0.17, 0.23, 0.13, -0.82, -1.96, 0.35, -0.07, -0.24, -0.77, 1.11, 0.88, -0.97, -0.66, 0.21, 1.13, 1.73, -1.63, -0.64, 0.46, -0.17, 0.61, 1.91, -2.8, 0.54, -0.17, 0.25, 0.73, 0.18, -0.09, -0.27, 0.11, -0.8, -0.36, 0.32, 0.29, 0.23, 0.52, 2.04, -0.44, 1.3, -0.22, -0.71, -1.53, 1.33, -1.61, -0.19, -1.27, -0.67, -0.2, -2.11, -0.85, -1.34, 0.33, -1.66, 1.72, -0.45, 0.42, -1.24, 1.9, 0.61, 0.01, -2.49, 0.19, -0.67, -1.19, 0.62, 1.21, -0.66, 0.84, -0.95, -0.37, 0.01, 0.56, 0.62, 0.85, 0.91, 0.09, -0.25, 1.87, 0.32, 0.8, 2.06, -0.25, 1.25, -0.56, 1.21, 0.0, -0.33, 0.79, -0.79], [-1.07, -0.46, 0.6, -1.11, -0.77, -0.48, -0.04, 0.14, 1.66, -0.92, -0.92, -0.0, -1.24, -0.1, -1.69, 1.2, -2.4, -0.33, -1.8, 1.05, -0.09, 1.26, 0.11, -0.23, -0.69, 1.2, -0.16, 0.65, -1.65, -0.04, 0.44, -0.98, 0.42, -2.2, 1.14, 1.75, -0.92, -0.49, 2.42, 0.06, -0.13, 0.11, -0.5, -2.34, 0.55, 0.01, -0.01, 0.4, -1.65, 0.89, -0.05, -0.56, 0.14, 2.22, -0.84, -0.23, 1.48, -1.33, -0.42, 1.01, -0.4, 0.27, 0.89, -0.37, 0.49, 0.27, -2.35, -0.48, 1.45, -0.74, 1.56, 1.35, 0.26, 0.01, 0.43, 0.63, 1.18, -0.44, -0.12, -1.43, 0.23, 0.68, 0.28, 0.92, 0.36, 0.21, 0.02, 1.02, 0.54, 1.35, -0.89, 0.46, 0.81, 0.32, -1.2, 0.34], [0.51, 0.11, 0.27, 0.54, 2.06, 0.83, -2.03, -0.61, 0.0, 0.96, 0.83, 0.32, 0.86, -0.96, -0.8, -2.17, 0.08, -0.67, 1.04, 0.19, -0.19, -1.04, 0.72, -0.16, 1.1, 0.75, -0.29, -0.69, -0.56, 0.94, 1.02, 1.23, -0.94, -1.39, -0.61, -0.35, 0.46, 0.78, 2.09, -1.47, -1.28, -3.4, -0.51, -1.12, 0.86, -0.59, 0.78, -0.29, -0.29, -0.75, -1.34, 1.82, 1.39, -0.37, -0.83, -0.24, -0.29, -0.11, 1.26, 0.11, -0.61, 1.23, 0.48, -0.48, -0.11, -1.1, 0.99, -0.35, 0.72, -1.04, -0.32, 0.67, -0.11, 1.1, 0.24, -2.09, 1.2, 0.8, 0.86, 2.41, -0.05, 0.96, -0.35, -1.26, -1.1, 0.38, 0.16, -0.21, -0.05, -0.48, -0.03, -0.11, -0.24, 0.32, 1.58, -1.58], [-0.15, -1.46, 0.2, 0.88, 1.41, 0.61, 1.7, 0.8, -1.27, 1.57, 0.27, 0.9, -0.68, 0.02, -1.15, 1.03, -1.2, -0.94, 0.21, 1.7, -0.65, 1.2, -1.0, -1.11, 1.49, -1.58, -1.23, 1.76, 0.95, -1.26, 1.8, -0.88, 1.81, -0.03, -0.07, -0.77, 0.8, -1.13, -0.64, -1.38, 1.56, 0.02, -0.2, -1.37, -0.83, -1.1, 0.06, -0.04, -0.86, -1.55, -1.2, -0.34, -1.04, -0.1, -0.82, -0.29, 1.13, 1.09, 0.77, -0.94, 0.41, -0.47, -1.48, 1.0, 1.61, -1.48, 1.01, 0.05, 0.75, 0.36, -0.7, 1.52, -0.92, -0.74, -0.47, -1.01, 0.8, 0.58, -0.09, -0.76, 0.37, 0.9, -0.41, 1.39, 0.53, 1.24, -1.55, 0.9, 1.24, -0.67, -1.05, -0.14, 0.12, 0.95, 0.18, -0.4]]}, "x": {"Batch": ["RunA", "RunC", "RunA", "RunC", "RunC", "RunA", "RunB", "RunB", "RunB", "RunC", "RunC", "RunC", "RunB", "RunA", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunB", "RunC", "RunA", "RunA", "RunC", "RunA", "RunC", "RunC", "RunC", "RunA", "RunB", "RunA", "RunC", "RunB", "RunB", "RunC", "RunA", "RunA", "RunA", "RunB", "RunA", "RunA", "RunB", "RunA", "RunA", "RunB", "RunA", "RunC", "RunC", "RunA", "RunC", "RunC", "RunA", "RunA", "RunC", "RunA", "RunB", "RunA", "RunB", "RunC", "RunB", "RunB", "RunB", "RunB", "RunC", "RunB", "RunB", "RunA", "RunA", "RunC", "RunB", "RunA", "RunB", "RunA", "RunB", "RunC", "RunC", "RunA", "RunA", "RunA", "RunC", "RunA", "RunC", "RunC", "RunA", "RunA", "RunA", "RunB", "RunC", "RunA", "RunC", "RunC"], "Library": ["PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "PolyA", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "RiboZero", "Exome", "RiboZero", "RiboZero", "RiboZero", "Exome", "RiboZero", "PolyA", "PolyA", "Exome", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "Exome", "RiboZero", "Exome", "PolyA", "Exome", "PolyA", "PolyA", "PolyA", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "RiboZero", "PolyA", "Exome", "Exome", "PolyA", "RiboZero", "RiboZero", "Exome", "Exome", "RiboZero", "PolyA", "Exome", "PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "Exome", "RiboZero", "PolyA", "Exome", "Exome", "Exome", "RiboZero", "RiboZero", "PolyA", "RiboZero", "Exome", "Exome", "RiboZero", "PolyA", "PolyA", "PolyA", "PolyA", "PolyA", "Exome", "RiboZero", "RiboZero", "PolyA", "Exome", "PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "Exome", "Exome"]}, "z": null}, "config": {"graphType": "Heatmap", "samplesClustered": true, "variablesClustered": true, "colorSpectrum": ["navy", "white", "firebrick3"], "title": "QC metrics (z-scored) \u2014 96 samples clustered"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
</section>
<section id="the-linked-triage-dashboard" class="level2">
<h2 class="anchored" data-anchor-id="the-linked-triage-dashboard">The linked triage dashboard</h2>
<p>Four panels over the <strong>same samples</strong>, all sharing <code>broadcastGroup: "qc"</code>. The sample is the unit, so each sample is a point and its lane/batch/library live in the per-sample annotation <code>z</code>. Select points in any panel and the same samples re-mark everywhere.</p>
<div id="b56999fe" class="cell" data-execution_count="3">
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Sample-centric: vars = samples (points), smps = metrics (axes), z = per-sample annotations.</span></span>
<span id="cb5-2">data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"y"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vars"</span>: samples, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"smps"</span>: metrics, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: [[raw[m][i] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> m <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> metrics] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(samples))]},</span>
<span id="cb5-3">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"z"</span>: annot}</span>
<span id="cb5-4"></span>
<span id="cb5-5"><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">def</span> panel(cfg, cid, w<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">640</span>, h<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">360</span>):</span>
<span id="cb5-6">    cfg <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">**</span>cfg, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"broadcast"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"broadcastGroup"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qc"</span>}</span>
<span id="cb5-7">    cx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CanvasXpress(render_to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cid, data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>data, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>cfg, width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>w, height<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>h)</span>
<span id="cb5-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> part <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> CXNoteBook(cx).render():</span>
<span id="cb5-9">        display(part)</span></code></pre></div>
</div>
<section id="mapping-rate-vs-duplication-the-triage-plot" class="level3">
<h3 class="anchored" data-anchor-id="mapping-rate-vs-duplication-the-triage-plot">1 — Mapping rate vs duplication (the triage plot)</h3>
<p>Bubble size is depth; failing libraries fall to the <strong>bottom-right</strong>. Lasso them here.</p>
<div id="8a232ed8" class="cell" data-execution_count="4">
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1">panel({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"xAxis"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_duplication"</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"yAxis"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_mapped"</span>],</span>
<span id="cb6-2">       <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"colorBy"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sizeBy"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total_reads"</span>,</span>
<span id="cb6-3">       <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mapping rate vs duplication — select the bottom-right"</span>}, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcMap"</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="qcMap" width="640" height="360"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("qcMap");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart qcMap removed for re-rendering.");
  } else {
    console.log("Chart qcMap ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart qcMap could not be cleaned for re-rendering:", error);
}

var chart_qcMap = new CanvasXpress({"renderTo": "qcMap", "data": {"y": {"vars": ["S001", "S002", "S003", "S004", "S005", "S006", "S007", "S008", "S009", "S010", "S011", "S012", "S013", "S014", "S015", "S016", "S017", "S018", "S019", "S020", "S021", "S022", "S023", "S024", "S025", "S026", "S027", "S028", "S029", "S030", "S031", "S032", "S033", "S034", "S035", "S036", "S037", "S038", "S039", "S040", "S041", "S042", "S043", "S044", "S045", "S046", "S047", "S048", "S049", "S050", "S051", "S052", "S053", "S054", "S055", "S056", "S057", "S058", "S059", "S060", "S061", "S062", "S063", "S064", "S065", "S066", "S067", "S068", "S069", "S070", "S071", "S072", "S073", "S074", "S075", "S076", "S077", "S078", "S079", "S080", "S081", "S082", "S083", "S084", "S085", "S086", "S087", "S088", "S089", "S090", "S091", "S092", "S093", "S094", "S095", "S096"], "smps": ["total_reads", "pct_mapped", "pct_duplication", "pct_q30", "gc_content", "insert_size", "contamination_freemix"], "data": [[39731273.0, 93.85, 11.9, 89.58, 44.63, 295.0, 0.0165], [40380961.0, 86.82, 13.41, 94.49, 46.71, 280.0, 0.0015], [32582992.0, 99.47, 7.88, 90.7, 50.27, 286.0, 0.0205], [53943211.0, 97.33, 13.95, 93.02, 44.51, 296.0, 0.0283], [44716872.0, 93.27, 11.08, 91.7, 45.65, 353.0, 0.0344], [36599101.0, 93.81, 13.99, 91.47, 46.64, 307.0, 0.0252], [46095164.0, 96.7, 19.76, 91.54, 48.13, 200.0, 0.0377], [48000008.0, 95.26, 18.89, 92.35, 48.73, 253.0, 0.0274], [36369073.0, 96.45, 13.29, 92.15, 53.85, 276.0, 0.0037], [50969240.0, 98.24, 29.2, 90.22, 45.15, 312.0, 0.0363], [33599116.0, 90.06, 14.99, 87.9, 45.15, 307.0, 0.0214], [48655822.0, 90.39, 24.5, 92.59, 48.25, 288.0, 0.0286], [49427201.0, 92.61, 11.81, 91.74, 44.08, 308.0, 0.0104], [47119993.0, 90.14, 10.41, 91.39, 47.9, 240.0, 0.0185], [46853194.0, 97.07, 5.44, 90.31, 42.56, 246.0, 0.005], [41603968.0, 86.13, 23.03, 94.13, 52.31, 195.0, 0.0301], [59046428.0, 92.89, 17.75, 93.67, 40.16, 279.0, 0.0045], [44160518.0, 96.46, 4.81, 89.9, 47.14, 251.0, 0.0074], [47727667.0, 89.67, 3.39, 90.54, 42.19, 315.0, 0.0206], [36724246.0, 89.8, 16.5, 92.31, 51.81, 283.0, 0.0378], [32834123.0, 79.02, 25.79, 94.17, 47.94, 269.0, 0.0108], [59130932.0, 97.62, 11.99, 95.4, 52.51, 237.0, 0.032], [44365467.0, 88.78, 23.6, 88.56, 48.62, 303.0, 0.0068], [50373280.0, 90.6, 7.17, 90.58, 47.49, 270.0, 0.0055], [27634567.0, 88.41, 2.91, 92.81, 45.91, 317.0, 0.0353], [55067555.0, 92.88, 6.01, 91.54, 52.3, 304.0, 0.0001], [47573074.0, 95.73, 10.26, 93.11, 47.71, 265.0, 0.0041], [26419904.0, 95.42, 18.8, 95.77, 50.43, 250.0, 0.0384], [44382069.0, 99.5, 6.25, 86.2, 42.67, 255.0, 0.0291], [30681013.0, 94.75, 16.45, 92.97, 48.13, 311.0, 0.0038], [44211734.0, 88.42, 10.6, 91.53, 49.74, 314.0, 0.0389], [37321516.0, 91.33, 21.43, 92.38, 44.94, 322.0, 0.0081], [51980437.0, 93.95, 8.86, 93.36, 49.68, 241.0, 0.039], [35908215.0, 89.48, 24.07, 92.25, 40.83, 224.0, 0.0179], [43841593.0, 90.38, 4.28, 91.69, 52.09, 253.0, 0.0174], [24751211.0, 94.05, 14.02, 91.33, 54.14, 263.0, 0.0094], [35531985.0, 89.94, 8.89, 92.11, 45.14, 293.0, 0.0274], [51665363.0, 89.7, 11.8, 90.25, 46.59, 305.0, 0.0053], [40270860.0, 92.83, 11.11, 91.15, 56.42, 354.0, 0.0109], [62194964.0, 94.15, 18.98, 92.54, 48.46, 221.0, 0.0024], [23130329.0, 88.7, 16.89, 92.46, 47.81, 228.0, 0.0362], [48105118.0, 93.37, 27.16, 92.35, 48.63, 149.0, 0.0185], [36035403.0, 95.84, 8.99, 92.94, 46.56, 257.0, 0.016], [51977734.0, 97.33, 17.13, 96.02, 40.34, 234.0, 0.0025], [39437507.0, 88.95, 10.68, 90.99, 50.1, 308.0, 0.0087], [33750550.0, 93.43, 5.63, 94.53, 48.28, 254.0, 0.0056], [45625993.0, 96.44, 11.56, 91.44, 48.23, 305.0, 0.0189], [39267219.0, 91.57, 11.44, 90.43, 49.61, 265.0, 0.0178], [43603870.0, 99.05, 10.52, 88.77, 42.68, 265.0, 0.0084], [26322443.0, 88.1, 20.0, 94.59, 51.26, 248.0, 0.0005], [50827140.0, 96.17, 11.95, 88.6, 48.08, 226.0, 0.0045], [40761784.0, 94.36, 22.35, 91.5, 46.36, 344.0, 0.0143], [47320485.0, 96.26, 10.22, 89.31, 48.72, 328.0, 0.0063], [43369554.0, 95.62, 15.79, 90.51, 55.74, 262.0, 0.0171], [40114772.0, 99.5, 6.46, 91.48, 45.43, 245.0, 0.0088], [22339638.0, 95.3, 8.38, 87.6, 47.46, 267.0, 0.0149], [34758883.0, 92.38, 6.17, 90.16, 53.23, 265.0, 0.0312], [51604859.0, 94.24, 21.01, 89.15, 43.77, 272.0, 0.0307], [43270147.0, 96.49, 11.69, 92.55, 46.85, 323.0, 0.0271], [34107245.0, 92.97, 4.57, 88.51, 51.67, 280.0, 0.0074], [44048770.0, 83.22, 22.92, 95.37, 46.89, 253.0, 0.0229], [32112102.0, 91.49, 18.3, 90.97, 49.17, 322.0, 0.0128], [29809698.0, 95.74, 12.41, 92.73, 51.25, 294.0, 0.0013], [47040642.0, 82.17, 31.35, 89.37, 46.99, 258.0, 0.0297], [29626002.0, 85.39, 31.62, 95.75, 49.92, 272.0, 0.0367], [47661306.0, 99.5, 8.65, 93.12, 49.15, 235.0, 0.0013], [33024620.0, 93.63, 15.27, 91.9, 40.33, 313.0, 0.0298], [50703414.0, 92.5, 15.47, 86.82, 46.62, 263.0, 0.0188], [37015975.0, 92.23, 7.66, 92.26, 53.15, 303.0, 0.0268], [48527426.0, 92.78, 22.69, 90.51, 45.75, 237.0, 0.0224], [42127399.0, 88.49, 12.67, 89.46, 53.53, 264.0, 0.0102], [48366188.0, 93.46, 6.95, 93.15, 52.82, 301.0, 0.0357], [44082084.0, 93.74, 10.84, 94.33, 49.12, 272.0, 0.0077], [30703825.0, 95.42, 20.6, 90.54, 48.28, 317.0, 0.0098], [34817148.0, 92.11, 12.25, 93.58, 49.7, 285.0, 0.0129], [30327242.0, 81.72, 21.48, 89.96, 50.38, 198.0, 0.0066], [35056118.0, 96.86, 10.9, 91.12, 52.24, 321.0, 0.0274], [38741227.0, 93.97, 12.2, 91.9, 46.75, 306.0, 0.0249], [51892586.0, 91.75, 20.37, 93.02, 47.86, 308.0, 0.0172], [48967691.0, 91.86, 15.16, 93.14, 43.43, 366.0, 0.0095], [53294644.0, 93.5, 8.04, 93.6, 49.02, 274.0, 0.0225], [49837358.0, 96.54, 14.74, 93.72, 50.56, 312.0, 0.0286], [46298909.0, 90.68, 13.94, 92.06, 49.18, 263.0, 0.0135], [69724382.0, 94.67, 15.69, 91.37, 51.37, 229.0, 0.0342], [51769934.0, 91.97, 4.04, 95.67, 49.45, 235.0, 0.0243], [31818466.0, 90.59, 19.49, 92.53, 48.97, 290.0, 0.0325], [38365238.0, 93.75, 5.95, 93.5, 48.33, 282.0, 0.0005], [37024697.0, 92.84, 19.93, 96.06, 51.7, 268.0, 0.0286], [54204131.0, 91.71, 11.97, 91.38, 50.06, 274.0, 0.0325], [37236193.0, 93.17, 19.11, 94.41, 52.82, 258.0, 0.0106], [44443845.0, 93.16, 20.34, 90.74, 45.25, 275.0, 0.0062], [51079846.0, 94.13, 26.21, 94.33, 49.79, 272.0, 0.0166], [30167587.0, 88.6, 22.03, 91.89, 50.98, 267.0, 0.0196], [49060567.0, 96.15, 15.06, 91.21, 49.33, 288.0, 0.0292], [53415711.0, 88.31, 15.27, 93.49, 44.19, 335.0, 0.0203], [44717772.0, 93.47, 15.0, 90.28, 49.4, 217.0, 0.0136]]}, "z": {"Lane": ["L4", "L5", "L4", "L1", "L4", "L7", "L7", "L4", "L5", "L7", "L3", "L1", "L2", "L1", "L1", "L3", "L8", "L2", "L6", "L8", "L3", "L5", "L6", "L8", "L6", "L2", "L2", "L4", "L6", "L8", "L2", "L1", "L4", "L1", "L4", "L4", "L5", "L7", "L8", "L8", "L7", "L6", "L5", "L8", "L6", "L5", "L4", "L1", "L5", "L5", "L8", "L7", "L5", "L5", "L6", "L8", "L4", "L1", "L7", "L7", "L3", "L7", "L5", "L3", "L3", "L8", "L1", "L7", "L6", "L4", "L1", "L8", "L6", "L5", "L5", "L3", "L4", "L7", "L7", "L2", "L7", "L1", "L7", "L8", "L2", "L2", "L4", "L5", "L6", "L2", "L1", "L8", "L3", "L2", "L4", "L8"], "Batch": ["RunA", "RunC", "RunA", "RunC", "RunC", "RunA", "RunB", "RunB", "RunB", "RunC", "RunC", "RunC", "RunB", "RunA", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunB", "RunC", "RunA", "RunA", "RunC", "RunA", "RunC", "RunC", "RunC", "RunA", "RunB", "RunA", "RunC", "RunB", "RunB", "RunC", "RunA", "RunA", "RunA", "RunB", "RunA", "RunA", "RunB", "RunA", "RunA", "RunB", "RunA", "RunC", "RunC", "RunA", "RunC", "RunC", "RunA", "RunA", "RunC", "RunA", "RunB", "RunA", "RunB", "RunC", "RunB", "RunB", "RunB", "RunB", "RunC", "RunB", "RunB", "RunA", "RunA", "RunC", "RunB", "RunA", "RunB", "RunA", "RunB", "RunC", "RunC", "RunA", "RunA", "RunA", "RunC", "RunA", "RunC", "RunC", "RunA", "RunA", "RunA", "RunB", "RunC", "RunA", "RunC", "RunC"], "Library": ["PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "PolyA", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "RiboZero", "Exome", "RiboZero", "RiboZero", "RiboZero", "Exome", "RiboZero", "PolyA", "PolyA", "Exome", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "Exome", "RiboZero", "Exome", "PolyA", "Exome", "PolyA", "PolyA", "PolyA", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "RiboZero", "PolyA", "Exome", "Exome", "PolyA", "RiboZero", "RiboZero", "Exome", "Exome", "RiboZero", "PolyA", "Exome", "PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "Exome", "RiboZero", "PolyA", "Exome", "Exome", "Exome", "RiboZero", "RiboZero", "PolyA", "RiboZero", "Exome", "Exome", "RiboZero", "PolyA", "PolyA", "PolyA", "PolyA", "PolyA", "Exome", "RiboZero", "RiboZero", "PolyA", "Exome", "PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "Exome", "Exome"]}, "x": null}, "config": {"graphType": "Scatter2D", "xAxis": ["pct_duplication"], "yAxis": ["pct_mapped"], "colorBy": "Batch", "sizeBy": "total_reads", "title": "Mapping rate vs duplication \u2014 select the bottom-right", "broadcast": true, "broadcastGroup": "qc"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
</section>
<section id="contamination-vs-mapping" class="level3">
<h3 class="anchored" data-anchor-id="contamination-vs-mapping">2 — Contamination vs mapping</h3>
<div id="4bdf91e5" class="cell" data-execution_count="5">
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1">panel({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"xAxis"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_mapped"</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"yAxis"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"contamination_freemix"</span>],</span>
<span id="cb7-2">       <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"colorBy"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Contamination (freemix) vs mapping rate"</span>}, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcContam"</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="qcContam" width="640" height="360"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("qcContam");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart qcContam removed for re-rendering.");
  } else {
    console.log("Chart qcContam ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart qcContam could not be cleaned for re-rendering:", error);
}

var chart_qcContam = new CanvasXpress({"renderTo": "qcContam", "data": {"y": {"vars": ["S001", "S002", "S003", "S004", "S005", "S006", "S007", "S008", "S009", "S010", "S011", "S012", "S013", "S014", "S015", "S016", "S017", "S018", "S019", "S020", "S021", "S022", "S023", "S024", "S025", "S026", "S027", "S028", "S029", "S030", "S031", "S032", "S033", "S034", "S035", "S036", "S037", "S038", "S039", "S040", "S041", "S042", "S043", "S044", "S045", "S046", "S047", "S048", "S049", "S050", "S051", "S052", "S053", "S054", "S055", "S056", "S057", "S058", "S059", "S060", "S061", "S062", "S063", "S064", "S065", "S066", "S067", "S068", "S069", "S070", "S071", "S072", "S073", "S074", "S075", "S076", "S077", "S078", "S079", "S080", "S081", "S082", "S083", "S084", "S085", "S086", "S087", "S088", "S089", "S090", "S091", "S092", "S093", "S094", "S095", "S096"], "smps": ["total_reads", "pct_mapped", "pct_duplication", "pct_q30", "gc_content", "insert_size", "contamination_freemix"], "data": [[39731273.0, 93.85, 11.9, 89.58, 44.63, 295.0, 0.0165], [40380961.0, 86.82, 13.41, 94.49, 46.71, 280.0, 0.0015], [32582992.0, 99.47, 7.88, 90.7, 50.27, 286.0, 0.0205], [53943211.0, 97.33, 13.95, 93.02, 44.51, 296.0, 0.0283], [44716872.0, 93.27, 11.08, 91.7, 45.65, 353.0, 0.0344], [36599101.0, 93.81, 13.99, 91.47, 46.64, 307.0, 0.0252], [46095164.0, 96.7, 19.76, 91.54, 48.13, 200.0, 0.0377], [48000008.0, 95.26, 18.89, 92.35, 48.73, 253.0, 0.0274], [36369073.0, 96.45, 13.29, 92.15, 53.85, 276.0, 0.0037], [50969240.0, 98.24, 29.2, 90.22, 45.15, 312.0, 0.0363], [33599116.0, 90.06, 14.99, 87.9, 45.15, 307.0, 0.0214], [48655822.0, 90.39, 24.5, 92.59, 48.25, 288.0, 0.0286], [49427201.0, 92.61, 11.81, 91.74, 44.08, 308.0, 0.0104], [47119993.0, 90.14, 10.41, 91.39, 47.9, 240.0, 0.0185], [46853194.0, 97.07, 5.44, 90.31, 42.56, 246.0, 0.005], [41603968.0, 86.13, 23.03, 94.13, 52.31, 195.0, 0.0301], [59046428.0, 92.89, 17.75, 93.67, 40.16, 279.0, 0.0045], [44160518.0, 96.46, 4.81, 89.9, 47.14, 251.0, 0.0074], [47727667.0, 89.67, 3.39, 90.54, 42.19, 315.0, 0.0206], [36724246.0, 89.8, 16.5, 92.31, 51.81, 283.0, 0.0378], [32834123.0, 79.02, 25.79, 94.17, 47.94, 269.0, 0.0108], [59130932.0, 97.62, 11.99, 95.4, 52.51, 237.0, 0.032], [44365467.0, 88.78, 23.6, 88.56, 48.62, 303.0, 0.0068], [50373280.0, 90.6, 7.17, 90.58, 47.49, 270.0, 0.0055], [27634567.0, 88.41, 2.91, 92.81, 45.91, 317.0, 0.0353], [55067555.0, 92.88, 6.01, 91.54, 52.3, 304.0, 0.0001], [47573074.0, 95.73, 10.26, 93.11, 47.71, 265.0, 0.0041], [26419904.0, 95.42, 18.8, 95.77, 50.43, 250.0, 0.0384], [44382069.0, 99.5, 6.25, 86.2, 42.67, 255.0, 0.0291], [30681013.0, 94.75, 16.45, 92.97, 48.13, 311.0, 0.0038], [44211734.0, 88.42, 10.6, 91.53, 49.74, 314.0, 0.0389], [37321516.0, 91.33, 21.43, 92.38, 44.94, 322.0, 0.0081], [51980437.0, 93.95, 8.86, 93.36, 49.68, 241.0, 0.039], [35908215.0, 89.48, 24.07, 92.25, 40.83, 224.0, 0.0179], [43841593.0, 90.38, 4.28, 91.69, 52.09, 253.0, 0.0174], [24751211.0, 94.05, 14.02, 91.33, 54.14, 263.0, 0.0094], [35531985.0, 89.94, 8.89, 92.11, 45.14, 293.0, 0.0274], [51665363.0, 89.7, 11.8, 90.25, 46.59, 305.0, 0.0053], [40270860.0, 92.83, 11.11, 91.15, 56.42, 354.0, 0.0109], [62194964.0, 94.15, 18.98, 92.54, 48.46, 221.0, 0.0024], [23130329.0, 88.7, 16.89, 92.46, 47.81, 228.0, 0.0362], [48105118.0, 93.37, 27.16, 92.35, 48.63, 149.0, 0.0185], [36035403.0, 95.84, 8.99, 92.94, 46.56, 257.0, 0.016], [51977734.0, 97.33, 17.13, 96.02, 40.34, 234.0, 0.0025], [39437507.0, 88.95, 10.68, 90.99, 50.1, 308.0, 0.0087], [33750550.0, 93.43, 5.63, 94.53, 48.28, 254.0, 0.0056], [45625993.0, 96.44, 11.56, 91.44, 48.23, 305.0, 0.0189], [39267219.0, 91.57, 11.44, 90.43, 49.61, 265.0, 0.0178], [43603870.0, 99.05, 10.52, 88.77, 42.68, 265.0, 0.0084], [26322443.0, 88.1, 20.0, 94.59, 51.26, 248.0, 0.0005], [50827140.0, 96.17, 11.95, 88.6, 48.08, 226.0, 0.0045], [40761784.0, 94.36, 22.35, 91.5, 46.36, 344.0, 0.0143], [47320485.0, 96.26, 10.22, 89.31, 48.72, 328.0, 0.0063], [43369554.0, 95.62, 15.79, 90.51, 55.74, 262.0, 0.0171], [40114772.0, 99.5, 6.46, 91.48, 45.43, 245.0, 0.0088], [22339638.0, 95.3, 8.38, 87.6, 47.46, 267.0, 0.0149], [34758883.0, 92.38, 6.17, 90.16, 53.23, 265.0, 0.0312], [51604859.0, 94.24, 21.01, 89.15, 43.77, 272.0, 0.0307], [43270147.0, 96.49, 11.69, 92.55, 46.85, 323.0, 0.0271], [34107245.0, 92.97, 4.57, 88.51, 51.67, 280.0, 0.0074], [44048770.0, 83.22, 22.92, 95.37, 46.89, 253.0, 0.0229], [32112102.0, 91.49, 18.3, 90.97, 49.17, 322.0, 0.0128], [29809698.0, 95.74, 12.41, 92.73, 51.25, 294.0, 0.0013], [47040642.0, 82.17, 31.35, 89.37, 46.99, 258.0, 0.0297], [29626002.0, 85.39, 31.62, 95.75, 49.92, 272.0, 0.0367], [47661306.0, 99.5, 8.65, 93.12, 49.15, 235.0, 0.0013], [33024620.0, 93.63, 15.27, 91.9, 40.33, 313.0, 0.0298], [50703414.0, 92.5, 15.47, 86.82, 46.62, 263.0, 0.0188], [37015975.0, 92.23, 7.66, 92.26, 53.15, 303.0, 0.0268], [48527426.0, 92.78, 22.69, 90.51, 45.75, 237.0, 0.0224], [42127399.0, 88.49, 12.67, 89.46, 53.53, 264.0, 0.0102], [48366188.0, 93.46, 6.95, 93.15, 52.82, 301.0, 0.0357], [44082084.0, 93.74, 10.84, 94.33, 49.12, 272.0, 0.0077], [30703825.0, 95.42, 20.6, 90.54, 48.28, 317.0, 0.0098], [34817148.0, 92.11, 12.25, 93.58, 49.7, 285.0, 0.0129], [30327242.0, 81.72, 21.48, 89.96, 50.38, 198.0, 0.0066], [35056118.0, 96.86, 10.9, 91.12, 52.24, 321.0, 0.0274], [38741227.0, 93.97, 12.2, 91.9, 46.75, 306.0, 0.0249], [51892586.0, 91.75, 20.37, 93.02, 47.86, 308.0, 0.0172], [48967691.0, 91.86, 15.16, 93.14, 43.43, 366.0, 0.0095], [53294644.0, 93.5, 8.04, 93.6, 49.02, 274.0, 0.0225], [49837358.0, 96.54, 14.74, 93.72, 50.56, 312.0, 0.0286], [46298909.0, 90.68, 13.94, 92.06, 49.18, 263.0, 0.0135], [69724382.0, 94.67, 15.69, 91.37, 51.37, 229.0, 0.0342], [51769934.0, 91.97, 4.04, 95.67, 49.45, 235.0, 0.0243], [31818466.0, 90.59, 19.49, 92.53, 48.97, 290.0, 0.0325], [38365238.0, 93.75, 5.95, 93.5, 48.33, 282.0, 0.0005], [37024697.0, 92.84, 19.93, 96.06, 51.7, 268.0, 0.0286], [54204131.0, 91.71, 11.97, 91.38, 50.06, 274.0, 0.0325], [37236193.0, 93.17, 19.11, 94.41, 52.82, 258.0, 0.0106], [44443845.0, 93.16, 20.34, 90.74, 45.25, 275.0, 0.0062], [51079846.0, 94.13, 26.21, 94.33, 49.79, 272.0, 0.0166], [30167587.0, 88.6, 22.03, 91.89, 50.98, 267.0, 0.0196], [49060567.0, 96.15, 15.06, 91.21, 49.33, 288.0, 0.0292], [53415711.0, 88.31, 15.27, 93.49, 44.19, 335.0, 0.0203], [44717772.0, 93.47, 15.0, 90.28, 49.4, 217.0, 0.0136]]}, "z": {"Lane": ["L4", "L5", "L4", "L1", "L4", "L7", "L7", "L4", "L5", "L7", "L3", "L1", "L2", "L1", "L1", "L3", "L8", "L2", "L6", "L8", "L3", "L5", "L6", "L8", "L6", "L2", "L2", "L4", "L6", "L8", "L2", "L1", "L4", "L1", "L4", "L4", "L5", "L7", "L8", "L8", "L7", "L6", "L5", "L8", "L6", "L5", "L4", "L1", "L5", "L5", "L8", "L7", "L5", "L5", "L6", "L8", "L4", "L1", "L7", "L7", "L3", "L7", "L5", "L3", "L3", "L8", "L1", "L7", "L6", "L4", "L1", "L8", "L6", "L5", "L5", "L3", "L4", "L7", "L7", "L2", "L7", "L1", "L7", "L8", "L2", "L2", "L4", "L5", "L6", "L2", "L1", "L8", "L3", "L2", "L4", "L8"], "Batch": ["RunA", "RunC", "RunA", "RunC", "RunC", "RunA", "RunB", "RunB", "RunB", "RunC", "RunC", "RunC", "RunB", "RunA", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunB", "RunC", "RunA", "RunA", "RunC", "RunA", "RunC", "RunC", "RunC", "RunA", "RunB", "RunA", "RunC", "RunB", "RunB", "RunC", "RunA", "RunA", "RunA", "RunB", "RunA", "RunA", "RunB", "RunA", "RunA", "RunB", "RunA", "RunC", "RunC", "RunA", "RunC", "RunC", "RunA", "RunA", "RunC", "RunA", "RunB", "RunA", "RunB", "RunC", "RunB", "RunB", "RunB", "RunB", "RunC", "RunB", "RunB", "RunA", "RunA", "RunC", "RunB", "RunA", "RunB", "RunA", "RunB", "RunC", "RunC", "RunA", "RunA", "RunA", "RunC", "RunA", "RunC", "RunC", "RunA", "RunA", "RunA", "RunB", "RunC", "RunA", "RunC", "RunC"], "Library": ["PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "PolyA", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "RiboZero", "Exome", "RiboZero", "RiboZero", "RiboZero", "Exome", "RiboZero", "PolyA", "PolyA", "Exome", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "Exome", "RiboZero", "Exome", "PolyA", "Exome", "PolyA", "PolyA", "PolyA", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "RiboZero", "PolyA", "Exome", "Exome", "PolyA", "RiboZero", "RiboZero", "Exome", "Exome", "RiboZero", "PolyA", "Exome", "PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "Exome", "RiboZero", "PolyA", "Exome", "Exome", "Exome", "RiboZero", "RiboZero", "PolyA", "RiboZero", "Exome", "Exome", "RiboZero", "PolyA", "PolyA", "PolyA", "PolyA", "PolyA", "Exome", "RiboZero", "RiboZero", "PolyA", "Exome", "PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "Exome", "Exome"]}, "x": null}, "config": {"graphType": "Scatter2D", "xAxis": ["pct_mapped"], "yAxis": ["contamination_freemix"], "colorBy": "Batch", "title": "Contamination (freemix) vs mapping rate", "broadcast": true, "broadcastGroup": "qc"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
</section>
<section id="q30-vs-gc-by-library-prep" class="level3">
<h3 class="anchored" data-anchor-id="q30-vs-gc-by-library-prep">3 — Q30 vs GC, by library prep</h3>
<div id="66a1edee" class="cell" data-execution_count="6">
<div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1">panel({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"xAxis"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gc_content"</span>], <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"yAxis"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_q30"</span>],</span>
<span id="cb8-2">       <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"colorBy"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Library"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Q30 vs GC content, coloured by library"</span>}, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcQ30"</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="qcQ30" width="640" height="360"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("qcQ30");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart qcQ30 removed for re-rendering.");
  } else {
    console.log("Chart qcQ30 ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart qcQ30 could not be cleaned for re-rendering:", error);
}

var chart_qcQ30 = new CanvasXpress({"renderTo": "qcQ30", "data": {"y": {"vars": ["S001", "S002", "S003", "S004", "S005", "S006", "S007", "S008", "S009", "S010", "S011", "S012", "S013", "S014", "S015", "S016", "S017", "S018", "S019", "S020", "S021", "S022", "S023", "S024", "S025", "S026", "S027", "S028", "S029", "S030", "S031", "S032", "S033", "S034", "S035", "S036", "S037", "S038", "S039", "S040", "S041", "S042", "S043", "S044", "S045", "S046", "S047", "S048", "S049", "S050", "S051", "S052", "S053", "S054", "S055", "S056", "S057", "S058", "S059", "S060", "S061", "S062", "S063", "S064", "S065", "S066", "S067", "S068", "S069", "S070", "S071", "S072", "S073", "S074", "S075", "S076", "S077", "S078", "S079", "S080", "S081", "S082", "S083", "S084", "S085", "S086", "S087", "S088", "S089", "S090", "S091", "S092", "S093", "S094", "S095", "S096"], "smps": ["total_reads", "pct_mapped", "pct_duplication", "pct_q30", "gc_content", "insert_size", "contamination_freemix"], "data": [[39731273.0, 93.85, 11.9, 89.58, 44.63, 295.0, 0.0165], [40380961.0, 86.82, 13.41, 94.49, 46.71, 280.0, 0.0015], [32582992.0, 99.47, 7.88, 90.7, 50.27, 286.0, 0.0205], [53943211.0, 97.33, 13.95, 93.02, 44.51, 296.0, 0.0283], [44716872.0, 93.27, 11.08, 91.7, 45.65, 353.0, 0.0344], [36599101.0, 93.81, 13.99, 91.47, 46.64, 307.0, 0.0252], [46095164.0, 96.7, 19.76, 91.54, 48.13, 200.0, 0.0377], [48000008.0, 95.26, 18.89, 92.35, 48.73, 253.0, 0.0274], [36369073.0, 96.45, 13.29, 92.15, 53.85, 276.0, 0.0037], [50969240.0, 98.24, 29.2, 90.22, 45.15, 312.0, 0.0363], [33599116.0, 90.06, 14.99, 87.9, 45.15, 307.0, 0.0214], [48655822.0, 90.39, 24.5, 92.59, 48.25, 288.0, 0.0286], [49427201.0, 92.61, 11.81, 91.74, 44.08, 308.0, 0.0104], [47119993.0, 90.14, 10.41, 91.39, 47.9, 240.0, 0.0185], [46853194.0, 97.07, 5.44, 90.31, 42.56, 246.0, 0.005], [41603968.0, 86.13, 23.03, 94.13, 52.31, 195.0, 0.0301], [59046428.0, 92.89, 17.75, 93.67, 40.16, 279.0, 0.0045], [44160518.0, 96.46, 4.81, 89.9, 47.14, 251.0, 0.0074], [47727667.0, 89.67, 3.39, 90.54, 42.19, 315.0, 0.0206], [36724246.0, 89.8, 16.5, 92.31, 51.81, 283.0, 0.0378], [32834123.0, 79.02, 25.79, 94.17, 47.94, 269.0, 0.0108], [59130932.0, 97.62, 11.99, 95.4, 52.51, 237.0, 0.032], [44365467.0, 88.78, 23.6, 88.56, 48.62, 303.0, 0.0068], [50373280.0, 90.6, 7.17, 90.58, 47.49, 270.0, 0.0055], [27634567.0, 88.41, 2.91, 92.81, 45.91, 317.0, 0.0353], [55067555.0, 92.88, 6.01, 91.54, 52.3, 304.0, 0.0001], [47573074.0, 95.73, 10.26, 93.11, 47.71, 265.0, 0.0041], [26419904.0, 95.42, 18.8, 95.77, 50.43, 250.0, 0.0384], [44382069.0, 99.5, 6.25, 86.2, 42.67, 255.0, 0.0291], [30681013.0, 94.75, 16.45, 92.97, 48.13, 311.0, 0.0038], [44211734.0, 88.42, 10.6, 91.53, 49.74, 314.0, 0.0389], [37321516.0, 91.33, 21.43, 92.38, 44.94, 322.0, 0.0081], [51980437.0, 93.95, 8.86, 93.36, 49.68, 241.0, 0.039], [35908215.0, 89.48, 24.07, 92.25, 40.83, 224.0, 0.0179], [43841593.0, 90.38, 4.28, 91.69, 52.09, 253.0, 0.0174], [24751211.0, 94.05, 14.02, 91.33, 54.14, 263.0, 0.0094], [35531985.0, 89.94, 8.89, 92.11, 45.14, 293.0, 0.0274], [51665363.0, 89.7, 11.8, 90.25, 46.59, 305.0, 0.0053], [40270860.0, 92.83, 11.11, 91.15, 56.42, 354.0, 0.0109], [62194964.0, 94.15, 18.98, 92.54, 48.46, 221.0, 0.0024], [23130329.0, 88.7, 16.89, 92.46, 47.81, 228.0, 0.0362], [48105118.0, 93.37, 27.16, 92.35, 48.63, 149.0, 0.0185], [36035403.0, 95.84, 8.99, 92.94, 46.56, 257.0, 0.016], [51977734.0, 97.33, 17.13, 96.02, 40.34, 234.0, 0.0025], [39437507.0, 88.95, 10.68, 90.99, 50.1, 308.0, 0.0087], [33750550.0, 93.43, 5.63, 94.53, 48.28, 254.0, 0.0056], [45625993.0, 96.44, 11.56, 91.44, 48.23, 305.0, 0.0189], [39267219.0, 91.57, 11.44, 90.43, 49.61, 265.0, 0.0178], [43603870.0, 99.05, 10.52, 88.77, 42.68, 265.0, 0.0084], [26322443.0, 88.1, 20.0, 94.59, 51.26, 248.0, 0.0005], [50827140.0, 96.17, 11.95, 88.6, 48.08, 226.0, 0.0045], [40761784.0, 94.36, 22.35, 91.5, 46.36, 344.0, 0.0143], [47320485.0, 96.26, 10.22, 89.31, 48.72, 328.0, 0.0063], [43369554.0, 95.62, 15.79, 90.51, 55.74, 262.0, 0.0171], [40114772.0, 99.5, 6.46, 91.48, 45.43, 245.0, 0.0088], [22339638.0, 95.3, 8.38, 87.6, 47.46, 267.0, 0.0149], [34758883.0, 92.38, 6.17, 90.16, 53.23, 265.0, 0.0312], [51604859.0, 94.24, 21.01, 89.15, 43.77, 272.0, 0.0307], [43270147.0, 96.49, 11.69, 92.55, 46.85, 323.0, 0.0271], [34107245.0, 92.97, 4.57, 88.51, 51.67, 280.0, 0.0074], [44048770.0, 83.22, 22.92, 95.37, 46.89, 253.0, 0.0229], [32112102.0, 91.49, 18.3, 90.97, 49.17, 322.0, 0.0128], [29809698.0, 95.74, 12.41, 92.73, 51.25, 294.0, 0.0013], [47040642.0, 82.17, 31.35, 89.37, 46.99, 258.0, 0.0297], [29626002.0, 85.39, 31.62, 95.75, 49.92, 272.0, 0.0367], [47661306.0, 99.5, 8.65, 93.12, 49.15, 235.0, 0.0013], [33024620.0, 93.63, 15.27, 91.9, 40.33, 313.0, 0.0298], [50703414.0, 92.5, 15.47, 86.82, 46.62, 263.0, 0.0188], [37015975.0, 92.23, 7.66, 92.26, 53.15, 303.0, 0.0268], [48527426.0, 92.78, 22.69, 90.51, 45.75, 237.0, 0.0224], [42127399.0, 88.49, 12.67, 89.46, 53.53, 264.0, 0.0102], [48366188.0, 93.46, 6.95, 93.15, 52.82, 301.0, 0.0357], [44082084.0, 93.74, 10.84, 94.33, 49.12, 272.0, 0.0077], [30703825.0, 95.42, 20.6, 90.54, 48.28, 317.0, 0.0098], [34817148.0, 92.11, 12.25, 93.58, 49.7, 285.0, 0.0129], [30327242.0, 81.72, 21.48, 89.96, 50.38, 198.0, 0.0066], [35056118.0, 96.86, 10.9, 91.12, 52.24, 321.0, 0.0274], [38741227.0, 93.97, 12.2, 91.9, 46.75, 306.0, 0.0249], [51892586.0, 91.75, 20.37, 93.02, 47.86, 308.0, 0.0172], [48967691.0, 91.86, 15.16, 93.14, 43.43, 366.0, 0.0095], [53294644.0, 93.5, 8.04, 93.6, 49.02, 274.0, 0.0225], [49837358.0, 96.54, 14.74, 93.72, 50.56, 312.0, 0.0286], [46298909.0, 90.68, 13.94, 92.06, 49.18, 263.0, 0.0135], [69724382.0, 94.67, 15.69, 91.37, 51.37, 229.0, 0.0342], [51769934.0, 91.97, 4.04, 95.67, 49.45, 235.0, 0.0243], [31818466.0, 90.59, 19.49, 92.53, 48.97, 290.0, 0.0325], [38365238.0, 93.75, 5.95, 93.5, 48.33, 282.0, 0.0005], [37024697.0, 92.84, 19.93, 96.06, 51.7, 268.0, 0.0286], [54204131.0, 91.71, 11.97, 91.38, 50.06, 274.0, 0.0325], [37236193.0, 93.17, 19.11, 94.41, 52.82, 258.0, 0.0106], [44443845.0, 93.16, 20.34, 90.74, 45.25, 275.0, 0.0062], [51079846.0, 94.13, 26.21, 94.33, 49.79, 272.0, 0.0166], [30167587.0, 88.6, 22.03, 91.89, 50.98, 267.0, 0.0196], [49060567.0, 96.15, 15.06, 91.21, 49.33, 288.0, 0.0292], [53415711.0, 88.31, 15.27, 93.49, 44.19, 335.0, 0.0203], [44717772.0, 93.47, 15.0, 90.28, 49.4, 217.0, 0.0136]]}, "z": {"Lane": ["L4", "L5", "L4", "L1", "L4", "L7", "L7", "L4", "L5", "L7", "L3", "L1", "L2", "L1", "L1", "L3", "L8", "L2", "L6", "L8", "L3", "L5", "L6", "L8", "L6", "L2", "L2", "L4", "L6", "L8", "L2", "L1", "L4", "L1", "L4", "L4", "L5", "L7", "L8", "L8", "L7", "L6", "L5", "L8", "L6", "L5", "L4", "L1", "L5", "L5", "L8", "L7", "L5", "L5", "L6", "L8", "L4", "L1", "L7", "L7", "L3", "L7", "L5", "L3", "L3", "L8", "L1", "L7", "L6", "L4", "L1", "L8", "L6", "L5", "L5", "L3", "L4", "L7", "L7", "L2", "L7", "L1", "L7", "L8", "L2", "L2", "L4", "L5", "L6", "L2", "L1", "L8", "L3", "L2", "L4", "L8"], "Batch": ["RunA", "RunC", "RunA", "RunC", "RunC", "RunA", "RunB", "RunB", "RunB", "RunC", "RunC", "RunC", "RunB", "RunA", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunB", "RunC", "RunA", "RunA", "RunC", "RunA", "RunC", "RunC", "RunC", "RunA", "RunB", "RunA", "RunC", "RunB", "RunB", "RunC", "RunA", "RunA", "RunA", "RunB", "RunA", "RunA", "RunB", "RunA", "RunA", "RunB", "RunA", "RunC", "RunC", "RunA", "RunC", "RunC", "RunA", "RunA", "RunC", "RunA", "RunB", "RunA", "RunB", "RunC", "RunB", "RunB", "RunB", "RunB", "RunC", "RunB", "RunB", "RunA", "RunA", "RunC", "RunB", "RunA", "RunB", "RunA", "RunB", "RunC", "RunC", "RunA", "RunA", "RunA", "RunC", "RunA", "RunC", "RunC", "RunA", "RunA", "RunA", "RunB", "RunC", "RunA", "RunC", "RunC"], "Library": ["PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "PolyA", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "RiboZero", "Exome", "RiboZero", "RiboZero", "RiboZero", "Exome", "RiboZero", "PolyA", "PolyA", "Exome", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "Exome", "RiboZero", "Exome", "PolyA", "Exome", "PolyA", "PolyA", "PolyA", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "RiboZero", "PolyA", "Exome", "Exome", "PolyA", "RiboZero", "RiboZero", "Exome", "Exome", "RiboZero", "PolyA", "Exome", "PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "Exome", "RiboZero", "PolyA", "Exome", "Exome", "Exome", "RiboZero", "RiboZero", "PolyA", "RiboZero", "Exome", "Exome", "RiboZero", "PolyA", "PolyA", "PolyA", "PolyA", "PolyA", "Exome", "RiboZero", "RiboZero", "PolyA", "Exome", "PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "Exome", "Exome"]}, "x": null}, "config": {"graphType": "Scatter2D", "xAxis": ["gc_content"], "yAxis": ["pct_q30"], "colorBy": "Library", "title": "Q30 vs GC content, coloured by library", "broadcast": true, "broadcastGroup": "qc"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
</section>
<section id="sequencing-depth-per-sample" class="level3">
<h3 class="anchored" data-anchor-id="sequencing-depth-per-sample">4 — Sequencing depth per sample</h3>
<div id="4d91e972" class="cell" data-execution_count="7">
<div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1">panel({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bar"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphOrientation"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vertical"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"xAxis"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total_reads"</span>],</span>
<span id="cb9-2">       <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"colorBy"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Total reads per sample (flag the short ones)"</span>}, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qcReads"</span>, w<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">820</span>, h<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="qcReads" width="820" height="300"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("qcReads");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart qcReads removed for re-rendering.");
  } else {
    console.log("Chart qcReads ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart qcReads could not be cleaned for re-rendering:", error);
}

var chart_qcReads = new CanvasXpress({"renderTo": "qcReads", "data": {"y": {"vars": ["S001", "S002", "S003", "S004", "S005", "S006", "S007", "S008", "S009", "S010", "S011", "S012", "S013", "S014", "S015", "S016", "S017", "S018", "S019", "S020", "S021", "S022", "S023", "S024", "S025", "S026", "S027", "S028", "S029", "S030", "S031", "S032", "S033", "S034", "S035", "S036", "S037", "S038", "S039", "S040", "S041", "S042", "S043", "S044", "S045", "S046", "S047", "S048", "S049", "S050", "S051", "S052", "S053", "S054", "S055", "S056", "S057", "S058", "S059", "S060", "S061", "S062", "S063", "S064", "S065", "S066", "S067", "S068", "S069", "S070", "S071", "S072", "S073", "S074", "S075", "S076", "S077", "S078", "S079", "S080", "S081", "S082", "S083", "S084", "S085", "S086", "S087", "S088", "S089", "S090", "S091", "S092", "S093", "S094", "S095", "S096"], "smps": ["total_reads", "pct_mapped", "pct_duplication", "pct_q30", "gc_content", "insert_size", "contamination_freemix"], "data": [[39731273.0, 93.85, 11.9, 89.58, 44.63, 295.0, 0.0165], [40380961.0, 86.82, 13.41, 94.49, 46.71, 280.0, 0.0015], [32582992.0, 99.47, 7.88, 90.7, 50.27, 286.0, 0.0205], [53943211.0, 97.33, 13.95, 93.02, 44.51, 296.0, 0.0283], [44716872.0, 93.27, 11.08, 91.7, 45.65, 353.0, 0.0344], [36599101.0, 93.81, 13.99, 91.47, 46.64, 307.0, 0.0252], [46095164.0, 96.7, 19.76, 91.54, 48.13, 200.0, 0.0377], [48000008.0, 95.26, 18.89, 92.35, 48.73, 253.0, 0.0274], [36369073.0, 96.45, 13.29, 92.15, 53.85, 276.0, 0.0037], [50969240.0, 98.24, 29.2, 90.22, 45.15, 312.0, 0.0363], [33599116.0, 90.06, 14.99, 87.9, 45.15, 307.0, 0.0214], [48655822.0, 90.39, 24.5, 92.59, 48.25, 288.0, 0.0286], [49427201.0, 92.61, 11.81, 91.74, 44.08, 308.0, 0.0104], [47119993.0, 90.14, 10.41, 91.39, 47.9, 240.0, 0.0185], [46853194.0, 97.07, 5.44, 90.31, 42.56, 246.0, 0.005], [41603968.0, 86.13, 23.03, 94.13, 52.31, 195.0, 0.0301], [59046428.0, 92.89, 17.75, 93.67, 40.16, 279.0, 0.0045], [44160518.0, 96.46, 4.81, 89.9, 47.14, 251.0, 0.0074], [47727667.0, 89.67, 3.39, 90.54, 42.19, 315.0, 0.0206], [36724246.0, 89.8, 16.5, 92.31, 51.81, 283.0, 0.0378], [32834123.0, 79.02, 25.79, 94.17, 47.94, 269.0, 0.0108], [59130932.0, 97.62, 11.99, 95.4, 52.51, 237.0, 0.032], [44365467.0, 88.78, 23.6, 88.56, 48.62, 303.0, 0.0068], [50373280.0, 90.6, 7.17, 90.58, 47.49, 270.0, 0.0055], [27634567.0, 88.41, 2.91, 92.81, 45.91, 317.0, 0.0353], [55067555.0, 92.88, 6.01, 91.54, 52.3, 304.0, 0.0001], [47573074.0, 95.73, 10.26, 93.11, 47.71, 265.0, 0.0041], [26419904.0, 95.42, 18.8, 95.77, 50.43, 250.0, 0.0384], [44382069.0, 99.5, 6.25, 86.2, 42.67, 255.0, 0.0291], [30681013.0, 94.75, 16.45, 92.97, 48.13, 311.0, 0.0038], [44211734.0, 88.42, 10.6, 91.53, 49.74, 314.0, 0.0389], [37321516.0, 91.33, 21.43, 92.38, 44.94, 322.0, 0.0081], [51980437.0, 93.95, 8.86, 93.36, 49.68, 241.0, 0.039], [35908215.0, 89.48, 24.07, 92.25, 40.83, 224.0, 0.0179], [43841593.0, 90.38, 4.28, 91.69, 52.09, 253.0, 0.0174], [24751211.0, 94.05, 14.02, 91.33, 54.14, 263.0, 0.0094], [35531985.0, 89.94, 8.89, 92.11, 45.14, 293.0, 0.0274], [51665363.0, 89.7, 11.8, 90.25, 46.59, 305.0, 0.0053], [40270860.0, 92.83, 11.11, 91.15, 56.42, 354.0, 0.0109], [62194964.0, 94.15, 18.98, 92.54, 48.46, 221.0, 0.0024], [23130329.0, 88.7, 16.89, 92.46, 47.81, 228.0, 0.0362], [48105118.0, 93.37, 27.16, 92.35, 48.63, 149.0, 0.0185], [36035403.0, 95.84, 8.99, 92.94, 46.56, 257.0, 0.016], [51977734.0, 97.33, 17.13, 96.02, 40.34, 234.0, 0.0025], [39437507.0, 88.95, 10.68, 90.99, 50.1, 308.0, 0.0087], [33750550.0, 93.43, 5.63, 94.53, 48.28, 254.0, 0.0056], [45625993.0, 96.44, 11.56, 91.44, 48.23, 305.0, 0.0189], [39267219.0, 91.57, 11.44, 90.43, 49.61, 265.0, 0.0178], [43603870.0, 99.05, 10.52, 88.77, 42.68, 265.0, 0.0084], [26322443.0, 88.1, 20.0, 94.59, 51.26, 248.0, 0.0005], [50827140.0, 96.17, 11.95, 88.6, 48.08, 226.0, 0.0045], [40761784.0, 94.36, 22.35, 91.5, 46.36, 344.0, 0.0143], [47320485.0, 96.26, 10.22, 89.31, 48.72, 328.0, 0.0063], [43369554.0, 95.62, 15.79, 90.51, 55.74, 262.0, 0.0171], [40114772.0, 99.5, 6.46, 91.48, 45.43, 245.0, 0.0088], [22339638.0, 95.3, 8.38, 87.6, 47.46, 267.0, 0.0149], [34758883.0, 92.38, 6.17, 90.16, 53.23, 265.0, 0.0312], [51604859.0, 94.24, 21.01, 89.15, 43.77, 272.0, 0.0307], [43270147.0, 96.49, 11.69, 92.55, 46.85, 323.0, 0.0271], [34107245.0, 92.97, 4.57, 88.51, 51.67, 280.0, 0.0074], [44048770.0, 83.22, 22.92, 95.37, 46.89, 253.0, 0.0229], [32112102.0, 91.49, 18.3, 90.97, 49.17, 322.0, 0.0128], [29809698.0, 95.74, 12.41, 92.73, 51.25, 294.0, 0.0013], [47040642.0, 82.17, 31.35, 89.37, 46.99, 258.0, 0.0297], [29626002.0, 85.39, 31.62, 95.75, 49.92, 272.0, 0.0367], [47661306.0, 99.5, 8.65, 93.12, 49.15, 235.0, 0.0013], [33024620.0, 93.63, 15.27, 91.9, 40.33, 313.0, 0.0298], [50703414.0, 92.5, 15.47, 86.82, 46.62, 263.0, 0.0188], [37015975.0, 92.23, 7.66, 92.26, 53.15, 303.0, 0.0268], [48527426.0, 92.78, 22.69, 90.51, 45.75, 237.0, 0.0224], [42127399.0, 88.49, 12.67, 89.46, 53.53, 264.0, 0.0102], [48366188.0, 93.46, 6.95, 93.15, 52.82, 301.0, 0.0357], [44082084.0, 93.74, 10.84, 94.33, 49.12, 272.0, 0.0077], [30703825.0, 95.42, 20.6, 90.54, 48.28, 317.0, 0.0098], [34817148.0, 92.11, 12.25, 93.58, 49.7, 285.0, 0.0129], [30327242.0, 81.72, 21.48, 89.96, 50.38, 198.0, 0.0066], [35056118.0, 96.86, 10.9, 91.12, 52.24, 321.0, 0.0274], [38741227.0, 93.97, 12.2, 91.9, 46.75, 306.0, 0.0249], [51892586.0, 91.75, 20.37, 93.02, 47.86, 308.0, 0.0172], [48967691.0, 91.86, 15.16, 93.14, 43.43, 366.0, 0.0095], [53294644.0, 93.5, 8.04, 93.6, 49.02, 274.0, 0.0225], [49837358.0, 96.54, 14.74, 93.72, 50.56, 312.0, 0.0286], [46298909.0, 90.68, 13.94, 92.06, 49.18, 263.0, 0.0135], [69724382.0, 94.67, 15.69, 91.37, 51.37, 229.0, 0.0342], [51769934.0, 91.97, 4.04, 95.67, 49.45, 235.0, 0.0243], [31818466.0, 90.59, 19.49, 92.53, 48.97, 290.0, 0.0325], [38365238.0, 93.75, 5.95, 93.5, 48.33, 282.0, 0.0005], [37024697.0, 92.84, 19.93, 96.06, 51.7, 268.0, 0.0286], [54204131.0, 91.71, 11.97, 91.38, 50.06, 274.0, 0.0325], [37236193.0, 93.17, 19.11, 94.41, 52.82, 258.0, 0.0106], [44443845.0, 93.16, 20.34, 90.74, 45.25, 275.0, 0.0062], [51079846.0, 94.13, 26.21, 94.33, 49.79, 272.0, 0.0166], [30167587.0, 88.6, 22.03, 91.89, 50.98, 267.0, 0.0196], [49060567.0, 96.15, 15.06, 91.21, 49.33, 288.0, 0.0292], [53415711.0, 88.31, 15.27, 93.49, 44.19, 335.0, 0.0203], [44717772.0, 93.47, 15.0, 90.28, 49.4, 217.0, 0.0136]]}, "z": {"Lane": ["L4", "L5", "L4", "L1", "L4", "L7", "L7", "L4", "L5", "L7", "L3", "L1", "L2", "L1", "L1", "L3", "L8", "L2", "L6", "L8", "L3", "L5", "L6", "L8", "L6", "L2", "L2", "L4", "L6", "L8", "L2", "L1", "L4", "L1", "L4", "L4", "L5", "L7", "L8", "L8", "L7", "L6", "L5", "L8", "L6", "L5", "L4", "L1", "L5", "L5", "L8", "L7", "L5", "L5", "L6", "L8", "L4", "L1", "L7", "L7", "L3", "L7", "L5", "L3", "L3", "L8", "L1", "L7", "L6", "L4", "L1", "L8", "L6", "L5", "L5", "L3", "L4", "L7", "L7", "L2", "L7", "L1", "L7", "L8", "L2", "L2", "L4", "L5", "L6", "L2", "L1", "L8", "L3", "L2", "L4", "L8"], "Batch": ["RunA", "RunC", "RunA", "RunC", "RunC", "RunA", "RunB", "RunB", "RunB", "RunC", "RunC", "RunC", "RunB", "RunA", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunC", "RunB", "RunC", "RunA", "RunA", "RunC", "RunA", "RunC", "RunC", "RunC", "RunA", "RunB", "RunA", "RunC", "RunB", "RunB", "RunC", "RunA", "RunA", "RunA", "RunB", "RunA", "RunA", "RunB", "RunA", "RunA", "RunB", "RunA", "RunC", "RunC", "RunA", "RunC", "RunC", "RunA", "RunA", "RunC", "RunA", "RunB", "RunA", "RunB", "RunC", "RunB", "RunB", "RunB", "RunB", "RunC", "RunB", "RunB", "RunA", "RunA", "RunC", "RunB", "RunA", "RunB", "RunA", "RunB", "RunC", "RunC", "RunA", "RunA", "RunA", "RunC", "RunA", "RunC", "RunC", "RunA", "RunA", "RunA", "RunB", "RunC", "RunA", "RunC", "RunC"], "Library": ["PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "PolyA", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "RiboZero", "Exome", "RiboZero", "RiboZero", "RiboZero", "Exome", "RiboZero", "PolyA", "PolyA", "Exome", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "Exome", "RiboZero", "Exome", "PolyA", "Exome", "PolyA", "PolyA", "PolyA", "RiboZero", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "RiboZero", "PolyA", "Exome", "Exome", "PolyA", "RiboZero", "RiboZero", "Exome", "Exome", "RiboZero", "PolyA", "Exome", "PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "Exome", "RiboZero", "PolyA", "Exome", "Exome", "Exome", "RiboZero", "RiboZero", "PolyA", "RiboZero", "Exome", "Exome", "RiboZero", "PolyA", "PolyA", "PolyA", "PolyA", "PolyA", "Exome", "RiboZero", "RiboZero", "PolyA", "Exome", "PolyA", "RiboZero", "RiboZero", "PolyA", "RiboZero", "RiboZero", "RiboZero", "Exome", "PolyA", "PolyA", "Exome", "Exome"]}, "x": null}, "config": {"graphType": "Bar", "graphOrientation": "vertical", "xAxis": ["total_reads"], "colorBy": "Batch", "title": "Total reads per sample (flag the short ones)", "broadcast": true, "broadcastGroup": "qc"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
<p>Lasso the bad cluster in panel 1 and panels 2–4 immediately restrict to those samples — you can read their contamination, library and depth without a single callback. The “wiring” is one shared group id.</p>
</section>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>Each panel is a portable <code>data</code> + <code>config</code> spec; the cross-filter is just a shared <code>broadcastGroup</code>. The same specs reproduce the dashboard from R or JavaScript, against the same <code>ngs-qc.csv</code>.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../network-graphs-in-python/">Interactive network graphs in Python</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Package: <a href="https://pypi.org/project/canvasxpress/" class="uri">https://pypi.org/project/canvasxpress/</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>canvasxpress</category>
  <category>dashboard</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/python/linked-dashboards-in-python/</guid>
  <pubDate>Fri, 30 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/python/linked-dashboards-in-python/thumbnail.png" medium="image" type="image/png" height="110" width="144"/>
</item>
<item>
  <title>Genome browser tracks in Python with canvasxpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/python/genome-tracks-in-python/</link>
  <description><![CDATA[ 




<p>A genome browser view stacks <strong>tracks</strong> that share one coordinate axis: coverage, gene models, variants. In Python this usually means <code>pyGenomeTracks</code> or a static matplotlib figure. Here we build an interactive, zoomable view with <a href="https://pypi.org/project/canvasxpress/">canvasxpress</a> — from one portable spec.</p>
<section id="install" class="level2">
<h2 class="anchored" data-anchor-id="install">Install</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install canvasxpress</span></code></pre></div>
</section>
<section id="the-data-shape" class="level2">
<h2 class="anchored" data-anchor-id="the-data-shape">The data shape</h2>
<p>A Genome figure is a list of <strong>tracks</strong> that share one coordinate axis — each with a <code>type</code>. Real browser views stack several: here we build four — <strong>gene models</strong> (<code>box</code>, multi-exon, connected), <strong>coverage across three tissues</strong> (<code>bar</code>), an <strong>expression heatmap</strong> (<code>heatmap</code>), and <strong>variant markers</strong> (<code>triangle</code>).</p>
<div id="a793e16b" class="cell" data-execution_count="1">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> random</span>
<span id="cb2-2">random.seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb2-3"></span>
<span id="cb2-4"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Gene models: each gene is a set of exon [start, end] intervals, drawn connected.</span></span>
<span id="cb2-5">genes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []</span>
<span id="cb2-6"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> j <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>):</span>
<span id="cb2-7">    start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">120</span></span>
<span id="cb2-8">    exons <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [[start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, start <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> k <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(random.randint(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>))]</span>
<span id="cb2-9">    genes.append({<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>: <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"GENE</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>j<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dir"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"right"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> j <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"left"</span>,</span>
<span id="cb2-10">                  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fill"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(70,130,220)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"outline"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(0,0,0)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: exons})</span>
<span id="cb2-11"></span>
<span id="cb2-12"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Coverage and expression: one entry per binned position, three tissues each.</span></span>
<span id="cb2-13">offsets  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">22</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">22</span>)]</span>
<span id="cb2-14">coverage <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>: <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"p</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"offset"</span>: o,</span>
<span id="cb2-15">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: [random.randint(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>), random.randint(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>), random.randint(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>)]}</span>
<span id="cb2-16">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, o <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(offsets)]</span>
<span id="cb2-17">express  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>: <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"p</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"offset"</span>: o,</span>
<span id="cb2-18">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: [<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(random.gauss(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)]}</span>
<span id="cb2-19">            <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, o <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(offsets)]</span>
<span id="cb2-20"></span>
<span id="cb2-21"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Variants: point markers at genomic positions.</span></span>
<span id="cb2-22">snps <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [{<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"id"</span>: <span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"rs</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span>k<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"offset"</span>: random.randint(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">520</span>),</span>
<span id="cb2-23">         <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fill"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(200,40,40)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"outline"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(0,0,0)"</span>} <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> k <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">9</span>)]</span>
<span id="cb2-24"></span>
<span id="cb2-25">data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"tracks"</span>: [</span>
<span id="cb2-26">    {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genes (exon models)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"type"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"box"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"connect"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: genes},</span>
<span id="cb2-27">    {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Coverage — Heart / Liver / Kidney"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"type"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bar"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"height"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">120</span>,</span>
<span id="cb2-28">     <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"fill"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(80,80,200)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"outline"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(60,60,60)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: coverage},</span>
<span id="cb2-29">    {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expression (z-score)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"type"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"heatmap"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"height"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">90</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: express},</span>
<span id="cb2-30">    {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"name"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SNPs"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"type"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"triangle"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: snps},</span>
<span id="cb2-31">]}</span></code></pre></div>
</div>
</section>
<section id="the-plot" class="level2">
<h2 class="anchored" data-anchor-id="the-plot">The plot</h2>
<div id="020b62c8" class="cell" data-execution_count="2">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.canvas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CanvasXpress</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.render.jupyter <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CXNoteBook</span>
<span id="cb3-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> IPython.display <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> display</span>
<span id="cb3-4"></span>
<span id="cb3-5">config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb3-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genome"</span>,</span>
<span id="cb3-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"background"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(245,245,245)"</span>,</span>
<span id="cb3-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"featureStaggered"</span>: <span class="va" style="color: #111111;
background-color: null;
font-style: inherit;">True</span>,</span>
<span id="cb3-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Multi-track genome browser: genes, coverage, expression and variants"</span>,</span>
<span id="cb3-10">}</span>
<span id="cb3-11"></span>
<span id="cb3-12">cx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CanvasXpress(render_to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"genome"</span>, data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>data, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>config, width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">760</span>, height<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">520</span>)</span>
<span id="cb3-13"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> part <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> CXNoteBook(cx).render():</span>
<span id="cb3-14">    display(part)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="genome" width="760" height="520"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("genome");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart genome removed for re-rendering.");
  } else {
    console.log("Chart genome ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart genome could not be cleaned for re-rendering:", error);
}

var chart_genome = new CanvasXpress({"renderTo": "genome", "data": {"tracks": [{"name": "Genes (exon models)", "type": "box", "connect": true, "data": [{"id": "GENE1", "dir": "right", "fill": "rgb(70,130,220)", "outline": "rgb(0,0,0)", "data": [[40, 58], [70, 88]]}, {"id": "GENE2", "dir": "left", "fill": "rgb(70,130,220)", "outline": "rgb(0,0,0)", "data": [[160, 178], [190, 208], [220, 238], [250, 268]]}, {"id": "GENE3", "dir": "right", "fill": "rgb(70,130,220)", "outline": "rgb(0,0,0)", "data": [[280, 298], [310, 328], [340, 358], [370, 388]]}, {"id": "GENE4", "dir": "left", "fill": "rgb(70,130,220)", "outline": "rgb(0,0,0)", "data": [[400, 418], [430, 448]]}]}, {"name": "Coverage \u2014 Heart / Liver / Kidney", "type": "bar", "height": 120, "fill": "rgb(80,80,200)", "outline": "rgb(60,60,60)", "data": [{"id": "p0", "offset": 50, "data": [31, 38, 45]}, {"id": "p1", "offset": 72, "data": [12, 8, 38]}, {"id": "p2", "offset": 94, "data": [24, 43, 22]}, {"id": "p3", "offset": 116, "data": [20, 38, 42]}, {"id": "p4", "offset": 138, "data": [43, 38, 33]}, {"id": "p5", "offset": 160, "data": [17, 22, 17]}, {"id": "p6", "offset": 182, "data": [41, 32, 8]}, {"id": "p7", "offset": 204, "data": [12, 18, 45]}, {"id": "p8", "offset": 226, "data": [10, 27, 9]}, {"id": "p9", "offset": 248, "data": [25, 38, 32]}, {"id": "p10", "offset": 270, "data": [35, 33, 44]}, {"id": "p11", "offset": 292, "data": [36, 16, 31]}, {"id": "p12", "offset": 314, "data": [14, 10, 16]}, {"id": "p13", "offset": 336, "data": [39, 21, 24]}, {"id": "p14", "offset": 358, "data": [35, 27, 34]}, {"id": "p15", "offset": 380, "data": [40, 32, 44]}, {"id": "p16", "offset": 402, "data": [30, 42, 45]}, {"id": "p17", "offset": 424, "data": [34, 45, 22]}, {"id": "p18", "offset": 446, "data": [29, 9, 25]}, {"id": "p19", "offset": 468, "data": [18, 28, 42]}, {"id": "p20", "offset": 490, "data": [44, 44, 14]}, {"id": "p21", "offset": 512, "data": [21, 44, 25]}]}, {"name": "Expression (z-score)", "type": "heatmap", "height": 90, "data": [{"id": "p0", "offset": 50, "data": [-0.08, 0.35, 1.84]}, {"id": "p1", "offset": 72, "data": [-2.41, 1.53, 0.95]}, {"id": "p2", "offset": 94, "data": [-0.48, 0.3, -0.47]}, {"id": "p3", "offset": 116, "data": [1.65, 0.21, -0.22]}, {"id": "p4", "offset": 138, "data": [-0.23, -0.2, -0.18]}, {"id": "p5", "offset": 160, "data": [-0.88, 2.06, -1.91]}, {"id": "p6", "offset": 182, "data": [-3.61, -0.12, -0.15]}, {"id": "p7", "offset": 204, "data": [0.37, -0.2, -0.15]}, {"id": "p8", "offset": 226, "data": [0.33, 0.97, -0.45]}, {"id": "p9", "offset": 248, "data": [-0.37, 1.94, 0.53]}, {"id": "p10", "offset": 270, "data": [-0.99, 2.32, 0.78]}, {"id": "p11", "offset": 292, "data": [-0.59, -1.17, 0.3]}, {"id": "p12", "offset": 314, "data": [-0.83, -1.06, -1.3]}, {"id": "p13", "offset": 336, "data": [-0.51, 1.11, -0.43]}, {"id": "p14", "offset": 358, "data": [-1.45, 0.67, 0.07]}, {"id": "p15", "offset": 380, "data": [0.84, 1.2, -0.17]}, {"id": "p16", "offset": 402, "data": [-0.14, -0.05, -1.13]}, {"id": "p17", "offset": 424, "data": [0.67, 1.37, 0.17]}, {"id": "p18", "offset": 446, "data": [-0.24, -0.26, -0.78]}, {"id": "p19", "offset": 468, "data": [-0.8, -0.4, -0.84]}, {"id": "p20", "offset": 490, "data": [-0.44, -1.58, 0.35]}, {"id": "p21", "offset": 512, "data": [0.05, -1.15, -2.3]}]}, {"name": "SNPs", "type": "triangle", "data": [{"id": "rs1000", "offset": 173, "fill": "rgb(200,40,40)", "outline": "rgb(0,0,0)"}, {"id": "rs1001", "offset": 366, "fill": "rgb(200,40,40)", "outline": "rgb(0,0,0)"}, {"id": "rs1002", "offset": 278, "fill": "rgb(200,40,40)", "outline": "rgb(0,0,0)"}, {"id": "rs1003", "offset": 197, "fill": "rgb(200,40,40)", "outline": "rgb(0,0,0)"}, {"id": "rs1004", "offset": 348, "fill": "rgb(200,40,40)", "outline": "rgb(0,0,0)"}, {"id": "rs1005", "offset": 352, "fill": "rgb(200,40,40)", "outline": "rgb(0,0,0)"}, {"id": "rs1006", "offset": 208, "fill": "rgb(200,40,40)", "outline": "rgb(0,0,0)"}, {"id": "rs1007", "offset": 135, "fill": "rgb(200,40,40)", "outline": "rgb(0,0,0)"}, {"id": "rs1008", "offset": 231, "fill": "rgb(200,40,40)", "outline": "rgb(0,0,0)"}]}], "x": null, "z": null}, "config": {"graphType": "Genome", "background": "rgb(245,245,245)", "featureStaggered": true, "title": "Multi-track genome browser: genes, coverage, expression and variants"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
<p>Scroll/drag to pan and zoom into a region; every track stays locked to the shared coordinate axis, so the gene models, coverage, expression and variants line up position-for-position. Swap each track for your own pileup, annotation and VCF-derived data.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The tracks and <code>config</code> <strong>are</strong> the figure — one portable JSON spec that renders the identical browser view from R or JavaScript, and can be validated and re-rendered later.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../network-graphs-in-python/">Interactive network graphs in Python</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Package: <a href="https://pypi.org/project/canvasxpress/" class="uri">https://pypi.org/project/canvasxpress/</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>canvasxpress</category>
  <category>genome</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/python/genome-tracks-in-python/</guid>
  <pubDate>Fri, 30 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/python/genome-tracks-in-python/thumbnail.png" medium="image" type="image/png" height="272" width="144"/>
</item>
<item>
  <title>Interactive network graphs in R with canvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/r/network-graphs-in-r/</link>
  <description><![CDATA[ 




<p>A network graph shows <strong>relationships</strong>: nodes connected by edges, laid out so that connected things sit near each other. The usual R reach is <code>igraph</code> or <code>networkD3</code>, but here we build one with <a href="https://canvasxpress.org">canvasXpress</a> — draggable, hover-labelled, force-directed, and <strong>reproducible</strong>, because the whole figure is one portable <code>data</code> + <code>config</code> spec.</p>
<section id="the-data-shape" class="level2">
<h2 class="anchored" data-anchor-id="the-data-shape">The data shape</h2>
<p>canvasXpress builds a network from two tables: <strong>nodes</strong> (<code>id</code>, <code>name</code>, <code>group</code>) and <strong>edges</strong> (<code>id1</code>, <code>id2</code>, <code>value</code>). Swap this simulated three-community graph for your own.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(canvasXpress)</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb1-4">grp   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Alpha"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Beta"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Gamma"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">7</span>)</span>
<span id="cb1-5">ids   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"n"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(grp))</span>
<span id="cb1-6">nodes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id =</span> ids, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(grp, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">ave</span>(grp, grp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">FUN =</span> seq_along)),</span>
<span id="cb1-7">                    <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">group =</span> grp, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stringsAsFactors =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb1-8"></span>
<span id="cb1-9"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Dense within a community, sparse between communities — the structure a layout reveals.</span></span>
<span id="cb1-10">e1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(); e2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(); ev <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>()</span>
<span id="cb1-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (g <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(grp)) {</span>
<span id="cb1-12">  m <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> ids[grp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> g]</span>
<span id="cb1-13">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (i <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(m)) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (j <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(m))</span>
<span id="cb1-14">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (i <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) { e1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(e1, m[i]); e2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(e2, m[j]); ev <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(ev, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)) }</span>
<span id="cb1-15">}</span>
<span id="cb1-16"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (k <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">6</span>) {                                     <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># a few cross-community links</span></span>
<span id="cb1-17">  pair <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(grp), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>)</span>
<span id="cb1-18">  e1 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(e1, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(ids[grp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> pair[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)); e2 <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(e2, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(ids[grp <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> pair[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>]], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)); ev <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(ev, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb1-19">}</span>
<span id="cb1-20">edges <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id1 =</span> e1, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id2 =</span> e2, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">value =</span> ev, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stringsAsFactors =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span></code></pre></div>
</div>
</section>
<section id="the-plot" class="level2">
<h2 class="anchored" data-anchor-id="the-plot">The plot</h2>
<p>Pass the two tables as <code>nodeData</code> and <code>edgeData</code>; <code>colorNodeBy</code> colours by the community, and <code>networkLayoutType = "forceDirected"</code> runs the physics simulation.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">canvasXpress</span>(</span>
<span id="cb2-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nodeData          =</span> nodes,</span>
<span id="cb2-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">edgeData          =</span> edges,</span>
<span id="cb2-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType         =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Network"</span>,</span>
<span id="cb2-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">networkLayoutType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"forceDirected"</span>,</span>
<span id="cb2-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colorNodeBy       =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"group"</span>,</span>
<span id="cb2-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nodeSize          =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>,</span>
<span id="cb2-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">showAnimation     =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb2-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title             =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"A small community network"</span>,</span>
<span id="cb2-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width             =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">650</span>,</span>
<span id="cb2-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height            =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">500</span></span>
<span id="cb2-12">)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-17b4dbd527e05259a22a" style="width:100%;height:500px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-17b4dbd527e05259a22a">{"x":{"data":{"nodes":[{"id":"n1","name":"Alpha1","group":"Alpha"},{"id":"n2","name":"Alpha2","group":"Alpha"},{"id":"n3","name":"Alpha3","group":"Alpha"},{"id":"n4","name":"Alpha4","group":"Alpha"},{"id":"n5","name":"Alpha5","group":"Alpha"},{"id":"n6","name":"Alpha6","group":"Alpha"},{"id":"n7","name":"Alpha7","group":"Alpha"},{"id":"n8","name":"Beta1","group":"Beta"},{"id":"n9","name":"Beta2","group":"Beta"},{"id":"n10","name":"Beta3","group":"Beta"},{"id":"n11","name":"Beta4","group":"Beta"},{"id":"n12","name":"Beta5","group":"Beta"},{"id":"n13","name":"Beta6","group":"Beta"},{"id":"n14","name":"Beta7","group":"Beta"},{"id":"n15","name":"Gamma1","group":"Gamma"},{"id":"n16","name":"Gamma2","group":"Gamma"},{"id":"n17","name":"Gamma3","group":"Gamma"},{"id":"n18","name":"Gamma4","group":"Gamma"},{"id":"n19","name":"Gamma5","group":"Gamma"},{"id":"n20","name":"Gamma6","group":"Gamma"},{"id":"n21","name":"Gamma7","group":"Gamma"}],"edges":[{"id1":"n1","id2":"n2","value":4},{"id1":"n1","id2":"n5","value":5},{"id1":"n2","id2":"n4","value":3},{"id1":"n2","id2":"n5","value":1},{"id1":"n2","id2":"n6","value":5},{"id1":"n2","id2":"n7","value":2},{"id1":"n3","id2":"n6","value":5},{"id1":"n3","id2":"n7","value":1},{"id1":"n4","id2":"n5","value":5},{"id1":"n4","id2":"n7","value":2},{"id1":"n5","id2":"n7","value":4},{"id1":"n8","id2":"n11","value":2},{"id1":"n9","id2":"n13","value":4},{"id1":"n10","id2":"n12","value":1},{"id1":"n10","id2":"n13","value":4},{"id1":"n10","id2":"n14","value":2},{"id1":"n11","id2":"n12","value":3},{"id1":"n11","id2":"n13","value":2},{"id1":"n12","id2":"n13","value":1},{"id1":"n12","id2":"n14","value":3},{"id1":"n15","id2":"n17","value":4},{"id1":"n15","id2":"n18","value":3},{"id1":"n15","id2":"n20","value":5},{"id1":"n15","id2":"n21","value":1},{"id1":"n16","id2":"n17","value":1},{"id1":"n16","id2":"n18","value":4},{"id1":"n16","id2":"n21","value":4},{"id1":"n17","id2":"n21","value":1},{"id1":"n18","id2":"n20","value":1},{"id1":"n20","id2":"n21","value":2},{"id1":"n10","id2":"n20","value":1},{"id1":"n14","id2":"n21","value":1},{"id1":"n16","id2":"n2","value":1},{"id1":"n3","id2":"n16","value":1},{"id1":"n19","id2":"n9","value":1},{"id1":"n7","id2":"n14","value":1}],"groups":null,"constraints":null},"config":{"graphType":"Network","isR":true,"networkLayoutType":"forceDirected","colorNodeBy":"group","nodeSize":25,"showAnimation":true,"title":"A small community network"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>Drag any node and the layout settles around it; hover to read the label. The three communities separate on their own because within-group edges outnumber the cross-group ones.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The nodes, edges and <code>config</code> <strong>are</strong> the figure — one portable specification. The same spec renders the identical network from Python or JavaScript, and can be validated and re-rendered later.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../sankey-diagrams-in-r/">Sankey / alluvial diagrams in R</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Package: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>R</category>
  <category>canvasXpress</category>
  <category>network</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/r/network-graphs-in-r/</guid>
  <pubDate>Thu, 29 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/r/network-graphs-in-r/thumbnail.png" medium="image" type="image/png" height="144" width="144"/>
</item>
<item>
  <title>An interactive NGS sequencing-QC dashboard in R with canvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/r/linked-dashboards-in-r/</link>
  <description><![CDATA[ 




<p>After a sequencing run you get a QC table — one row per sample, a dozen metrics — and you need to answer three questions fast: <strong>which samples fail, is a whole batch off, and are the failures correlated?</strong> A single scatter can’t do it; you want several views that <strong>talk to each other</strong> — 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 <strong>broadcast group</strong> and a selection broadcasts to all of them. Here we build a real QC dashboard for 96 RNA/exome samples.</p>
<section id="the-qc-table" class="level2">
<h2 class="anchored" data-anchor-id="the-qc-table">The QC table</h2>
<p>96 samples with mapping rate, duplication, Q30, GC, insert size and contamination (VerifyBamID <code>freemix</code>), plus lane / batch / library annotations. (Download: <a href="ngs-qc.csv"><code>ngs-qc.csv</code></a>.)</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(canvasXpress)</span>
<span id="cb1-2"></span>
<span id="cb1-3">qc <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read.csv</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ngs-qc.csv"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stringsAsFactors =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>)</span>
<span id="cb1-4">metrics <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total_reads"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_mapped"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_duplication"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_q30"</span>,</span>
<span id="cb1-5">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gc_content"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"insert_size"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"contamination_freemix"</span>)</span>
<span id="cb1-6"></span>
<span id="cb1-7">m        <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.matrix</span>(qc[, metrics]); <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rownames</span>(m) <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> qc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sample</span>
<span id="cb1-8">annot    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Lane =</span> qc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>lane, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Batch =</span> qc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>batch, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Library =</span> qc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>library,</span>
<span id="cb1-9">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> qc<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>sample)</span>
<span id="cb1-10"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(qc[, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sample"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"batch"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"library"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_mapped"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_duplication"</span>,</span>
<span id="cb1-11">            <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"contamination_freemix"</span>)], <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>  sample batch  library pct_mapped pct_duplication contamination_freemix
1   S001  RunA    PolyA      93.85           11.90                0.0165
2   S002  RunC RiboZero      86.82           13.41                0.0015
3   S003  RunA RiboZero      99.47            7.88                0.0205
4   S004  RunC    PolyA      97.33           13.95                0.0283</code></pre>
</div>
</div>
</section>
<section id="overview-a-clustered-qc-heatmap" class="level2">
<h2 class="anchored" data-anchor-id="overview-a-clustered-qc-heatmap">Overview — a clustered QC heatmap</h2>
<p>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.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">canvasXpress</span>(</span>
<span id="cb3-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">t</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">scale</span>(m)), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">smpAnnot =</span> annot,</span>
<span id="cb3-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heatmap"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">samplesClustered =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">variablesClustered =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb3-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colorSpectrum =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"navy"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"white"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"firebrick3"</span>),</span>
<span id="cb3-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"QC metrics (z-scored) — 96 samples clustered"</span>,</span>
<span id="cb3-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">820</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">420</span></span>
<span id="cb3-7">)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-5499ac24958b2a2488c0" style="width:100%;height:332px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-5499ac24958b2a2488c0">{"x":{"data":{"y":{"vars":["total_reads","pct_mapped","pct_duplication","pct_q30","gc_content","insert_size","contamination_freemix"],"smps":["S001","S002","S003","S004","S005","S006","S007","S008","S009","S010","S011","S012","S013","S014","S015","S016","S017","S018","S019","S020","S021","S022","S023","S024","S025","S026","S027","S028","S029","S030","S031","S032","S033","S034","S035","S036","S037","S038","S039","S040","S041","S042","S043","S044","S045","S046","S047","S048","S049","S050","S051","S052","S053","S054","S055","S056","S057","S058","S059","S060","S061","S062","S063","S064","S065","S066","S067","S068","S069","S070","S071","S072","S073","S074","S075","S076","S077","S078","S079","S080","S081","S082","S083","S084","S085","S086","S087","S088","S089","S090","S091","S092","S093","S094","S095","S096"],"data":[[-0.2964,-0.225,-1.081,1.264,0.2511,-0.6403,0.4025,0.6116,-0.6655,0.9377,-0.9697,0.6836,0.7683,0.515,0.4857,-0.09071,1.825,0.19,0.5817,-0.6265,-1.054,1.834,0.2125,0.8722,-1.625,1.388,0.5647,-1.758,0.2143,-1.29,0.1956,-0.561,1.049,-0.7162,0.155,-1.941,-0.7575,1.014,-0.2371,2.17,-2.119,0.6232,-0.7022,1.048,-0.3286,-0.9531,0.3509,-0.3473,0.1289,-1.769,0.9221,-0.1832,0.537,0.1032,-0.2542,-2.206,-0.8424,1.007,0.09225,-0.9139,0.1777,-1.133,-1.386,0.5063,-1.406,0.5744,-1.033,0.9085,-0.5945,0.6695,-0.03324,0.6518,0.1814,-1.288,-0.836,-1.329,-0.8097,-0.4051,1.039,0.7179,1.193,0.8134,0.4248,2.997,1.026,-1.165,-0.4464,-0.5936,1.293,-0.5703,0.2211,0.9498,-1.347,0.7281,1.206,0.2512],[0.2887,-1.501,1.719,1.174,0.1411,0.2785,1.014,0.6476,0.9505,1.406,-0.6759,-0.5919,-0.02688,-0.6555,1.108,-1.676,0.04438,0.953,-0.7752,-0.7421,-3.486,1.248,-1.002,-0.5385,-1.096,0.04184,0.7672,0.6883,1.727,0.5178,-1.093,-0.3527,0.3142,-0.8235,-0.5945,0.3396,-0.7064,-0.7675,0.02911,0.3651,-1.022,0.1665,0.7952,1.174,-0.9584,0.1818,0.9479,-0.2916,1.612,-1.175,0.8792,0.4185,0.9021,0.7392,1.727,0.6578,-0.08542,0.388,0.9606,0.06474,-2.417,-0.3119,0.7698,-2.684,-1.865,1.727,0.2327,-0.05488,-0.1236,0.01638,-1.075,0.1895,0.2607,0.6883,-0.1541,-2.799,1.055,0.3193,-0.2458,-0.2178,0.1996,0.9734,-0.5181,0.4974,-0.1898,-0.541,0.2633,0.03166,-0.2559,0.1156,0.1131,0.36,-1.047,0.8741,-1.121,0.192],[-0.3825,-0.1534,-0.9925,-0.07146,-0.5069,-0.06539,0.8101,0.6781,-0.1716,2.243,0.08635,1.529,-0.3962,-0.6086,-1.363,1.306,0.5051,-1.458,-1.674,0.3155,1.725,-0.3689,1.393,-1.1,-1.747,-1.276,-0.6314,0.6645,-1.24,0.3079,-0.5798,1.064,-0.8438,1.464,-1.539,-0.06084,-0.8393,-0.3977,-0.5024,0.6918,0.3747,1.933,-0.8241,0.4111,-0.5676,-1.334,-0.4341,-0.4523,-0.5919,0.8466,-0.3749,1.203,-0.6374,0.2077,-1.208,-0.9166,-1.252,0.9998,-0.4144,-1.495,1.29,0.5886,-0.3051,2.569,2.61,-0.8757,0.1288,0.1592,-1.026,1.255,-0.2657,-1.134,-0.5434,0.9376,-0.3294,1.071,-0.5343,-0.337,0.9027,0.1121,-0.9682,0.04841,-0.07298,0.1926,-1.575,0.7692,-1.285,0.8359,-0.3719,0.7115,0.8981,1.789,1.155,0.09697,0.1288,0.08787],[-1.127,1.278,-0.5781,0.558,-0.08841,-0.201,-0.1668,0.2299,0.132,-0.8132,-1.949,0.3474,-0.06882,-0.2402,-0.7691,1.102,0.8763,-0.9699,-0.6565,0.2103,1.121,1.724,-1.626,-0.6369,0.4552,-0.1668,0.6021,1.905,-2.782,0.5335,-0.1717,0.2446,0.7245,0.1809,-0.0933,-0.2696,0.1124,-0.7985,-0.3578,0.323,0.2838,0.2299,0.5189,2.027,-0.4361,1.298,-0.2157,-0.7104,-1.523,1.327,-1.607,-0.1863,-1.259,-0.6712,-0.1961,-2.096,-0.8426,-1.337,0.3279,-1.651,1.709,-0.4459,0.416,-1.229,1.895,0.607,0.009539,-2.478,0.1858,-0.6712,-1.185,0.6217,1.2,-0.6565,0.8323,-0.9405,-0.3724,0.009539,0.558,0.6168,0.8421,0.9008,0.0879,-0.25,1.856,0.3181,0.7931,2.047,-0.2451,1.239,-0.5585,1.2,0.004642,-0.3284,0.7882,-0.7838],[-1.068,-0.4543,0.5953,-1.103,-0.7669,-0.475,-0.03569,0.1412,1.651,-0.9143,-0.9143,-0.0003071,-1.23,-0.1035,-1.678,1.197,-2.386,-0.3276,-1.787,1.049,-0.09171,1.256,0.1088,-0.2244,-0.6902,1.194,-0.1595,0.6424,-1.645,-0.03569,0.439,-0.9762,0.4213,-2.188,1.132,1.736,-0.9172,-0.4897,2.408,0.06161,-0.13,0.1117,-0.4986,-2.332,0.5451,0.008538,-0.006204,0.4007,-1.643,0.8871,-0.05043,-0.5575,0.1383,2.208,-0.8317,-0.2332,1.468,-1.321,-0.4131,1.008,-0.4013,0.2709,0.8842,-0.3718,0.4921,0.265,-2.335,-0.4809,1.444,-0.7374,1.556,1.347,0.2562,0.008538,0.4272,0.6277,1.176,-0.4426,-0.1153,-1.421,0.2267,0.6808,0.2739,0.9196,0.3535,0.212,0.02328,1.017,0.5333,1.347,-0.8848,0.4537,0.8046,0.3181,-1.197,0.3388],[0.5064,0.1073,0.2669,0.5331,2.05,0.8258,-2.022,-0.6112,0.0008316,0.9588,0.8258,0.3202,0.8524,-0.9572,-0.7975,-2.155,0.08066,-0.6644,1.039,0.1871,-0.1854,-1.037,0.7193,-0.1588,1.092,0.7459,-0.2919,-0.6911,-0.558,0.9322,1.012,1.225,-0.9306,-1.383,-0.6112,-0.3451,0.4532,0.7726,2.076,-1.463,-1.276,-3.379,-0.5048,-1.117,0.8524,-0.5846,0.7726,-0.2919,-0.2919,-0.7443,-1.33,1.81,1.385,-0.3717,-0.8241,-0.2387,-0.2919,-0.1056,1.252,0.1073,-0.6112,1.225,0.4798,-0.4782,-0.1056,-1.09,0.9854,-0.3451,0.7193,-1.037,-0.3185,0.6661,-0.1056,1.092,0.2403,-2.075,1.198,0.7992,0.8524,2.396,-0.05239,0.9588,-0.3451,-1.25,-1.09,0.3734,0.1605,-0.2121,-0.05239,-0.4782,-0.02578,-0.1056,-0.2387,0.3202,1.571,-1.569],[-0.1512,-1.451,0.1955,0.8715,1.4,0.6028,1.686,0.7935,-1.261,1.565,0.2735,0.8975,-0.6799,0.02212,-1.148,1.028,-1.191,-0.9399,0.2041,1.695,-0.6453,1.192,-0.9919,-1.105,1.478,-1.573,-1.226,1.747,0.9408,-1.252,1.79,-0.8793,1.799,-0.02988,-0.07322,-0.7666,0.7935,-1.122,-0.6366,-1.373,1.556,0.02212,-0.1946,-1.365,-0.8273,-1.096,0.05679,-0.03855,-0.8533,-1.538,-1.191,-0.3419,-1.035,-0.09922,-0.8186,-0.2899,1.123,1.08,0.7675,-0.9399,0.4035,-0.4719,-1.469,0.9928,1.6,-1.469,1.002,0.04812,0.7415,0.3601,-0.6973,1.513,-0.9139,-0.7319,-0.4632,-1.009,0.7935,0.5768,-0.09055,-0.7579,0.3688,0.8975,-0.4112,1.383,0.5248,1.236,-1.538,0.8975,1.236,-0.6626,-1.044,-0.1426,0.1175,0.9495,0.1781,-0.4026]]},"x":{"Lane":["L4","L5","L4","L1","L4","L7","L7","L4","L5","L7","L3","L1","L2","L1","L1","L3","L8","L2","L6","L8","L3","L5","L6","L8","L6","L2","L2","L4","L6","L8","L2","L1","L4","L1","L4","L4","L5","L7","L8","L8","L7","L6","L5","L8","L6","L5","L4","L1","L5","L5","L8","L7","L5","L5","L6","L8","L4","L1","L7","L7","L3","L7","L5","L3","L3","L8","L1","L7","L6","L4","L1","L8","L6","L5","L5","L3","L4","L7","L7","L2","L7","L1","L7","L8","L2","L2","L4","L5","L6","L2","L1","L8","L3","L2","L4","L8"],"Batch":["RunA","RunC","RunA","RunC","RunC","RunA","RunB","RunB","RunB","RunC","RunC","RunC","RunB","RunA","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunB","RunC","RunA","RunA","RunC","RunA","RunC","RunC","RunC","RunA","RunB","RunA","RunC","RunB","RunB","RunC","RunA","RunA","RunA","RunB","RunA","RunA","RunB","RunA","RunA","RunB","RunA","RunC","RunC","RunA","RunC","RunC","RunA","RunA","RunC","RunA","RunB","RunA","RunB","RunC","RunB","RunB","RunB","RunB","RunC","RunB","RunB","RunA","RunA","RunC","RunB","RunA","RunB","RunA","RunB","RunC","RunC","RunA","RunA","RunA","RunC","RunA","RunC","RunC","RunA","RunA","RunA","RunB","RunC","RunA","RunC","RunC"],"Library":["PolyA","RiboZero","RiboZero","PolyA","RiboZero","PolyA","RiboZero","RiboZero","Exome","PolyA","PolyA","RiboZero","Exome","RiboZero","RiboZero","RiboZero","Exome","RiboZero","PolyA","PolyA","Exome","RiboZero","RiboZero","RiboZero","RiboZero","RiboZero","RiboZero","Exome","PolyA","PolyA","Exome","RiboZero","Exome","PolyA","Exome","PolyA","PolyA","PolyA","RiboZero","RiboZero","RiboZero","RiboZero","Exome","PolyA","RiboZero","PolyA","Exome","Exome","PolyA","RiboZero","RiboZero","Exome","Exome","RiboZero","PolyA","Exome","PolyA","RiboZero","RiboZero","PolyA","RiboZero","Exome","RiboZero","PolyA","Exome","Exome","Exome","RiboZero","RiboZero","PolyA","RiboZero","Exome","Exome","RiboZero","PolyA","PolyA","PolyA","PolyA","PolyA","Exome","RiboZero","RiboZero","PolyA","Exome","PolyA","RiboZero","RiboZero","PolyA","RiboZero","RiboZero","RiboZero","Exome","PolyA","PolyA","Exome","Exome"]},"z":null},"config":{"graphType":"Heatmap","isR":true,"samplesClustered":true,"variablesClustered":true,"colorSpectrum":["navy","white","firebrick3"],"title":"QC metrics (z-scored) — 96 samples clustered"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
</section>
<section id="the-linked-triage-dashboard" class="level2">
<h2 class="anchored" data-anchor-id="the-linked-triage-dashboard">The linked triage dashboard</h2>
<p>Four panels over the <strong>same samples</strong>, all sharing <code>broadcastGroup = "qc"</code>. The sample is the unit, so each sample is a point (<code>varAnnot</code> 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.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb4-1">qc_panel <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(cfg, ...) {</span>
<span id="cb4-2">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">do.call</span>(canvasXpress, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> m, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">varAnnot =</span> annot,</span>
<span id="cb4-3">                               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">broadcast =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">broadcastGroup =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"qc"</span>), cfg, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(...)))</span>
<span id="cb4-4">}</span></code></pre></div>
</div>
<section id="mapping-rate-vs-duplication-the-triage-plot" class="level3">
<h3 class="anchored" data-anchor-id="mapping-rate-vs-duplication-the-triage-plot">1 — Mapping rate vs duplication (the triage plot)</h3>
<p>Bubble size is depth; failing libraries fall to the <strong>bottom-right</strong> (low mapping, high duplication). Lasso them here.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qc_panel</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xAxis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_duplication"</span>),</span>
<span id="cb5-2">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yAxis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_mapped"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colorBy =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sizeBy =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total_reads"</span>,</span>
<span id="cb5-3">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mapping rate vs duplication — select the bottom-right"</span>),</span>
<span id="cb5-4">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">640</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">360</span>)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-ce36bb04be8a05559609" style="width:100%;height:365px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-ce36bb04be8a05559609">{"x":{"data":{"y":{"vars":["S001","S002","S003","S004","S005","S006","S007","S008","S009","S010","S011","S012","S013","S014","S015","S016","S017","S018","S019","S020","S021","S022","S023","S024","S025","S026","S027","S028","S029","S030","S031","S032","S033","S034","S035","S036","S037","S038","S039","S040","S041","S042","S043","S044","S045","S046","S047","S048","S049","S050","S051","S052","S053","S054","S055","S056","S057","S058","S059","S060","S061","S062","S063","S064","S065","S066","S067","S068","S069","S070","S071","S072","S073","S074","S075","S076","S077","S078","S079","S080","S081","S082","S083","S084","S085","S086","S087","S088","S089","S090","S091","S092","S093","S094","S095","S096"],"smps":["total_reads","pct_mapped","pct_duplication","pct_q30","gc_content","insert_size","contamination_freemix"],"data":[[3.973e+07,93.85,11.9,89.58,44.63,295,0.0165],[4.038e+07,86.82,13.41,94.49,46.71,280,0.0015],[3.258e+07,99.47,7.88,90.7,50.27,286,0.0205],[5.394e+07,97.33,13.95,93.02,44.51,296,0.0283],[4.472e+07,93.27,11.08,91.7,45.65,353,0.0344],[3.66e+07,93.81,13.99,91.47,46.64,307,0.0252],[4.61e+07,96.7,19.76,91.54,48.13,200,0.0377],[4.8e+07,95.26,18.89,92.35,48.73,253,0.0274],[3.637e+07,96.45,13.29,92.15,53.85,276,0.0037],[5.097e+07,98.24,29.2,90.22,45.15,312,0.0363],[3.36e+07,90.06,14.99,87.9,45.15,307,0.0214],[4.866e+07,90.39,24.5,92.59,48.25,288,0.0286],[4.943e+07,92.61,11.81,91.74,44.08,308,0.0104],[4.712e+07,90.14,10.41,91.39,47.9,240,0.0185],[4.685e+07,97.07,5.44,90.31,42.56,246,0.005],[4.16e+07,86.13,23.03,94.13,52.31,195,0.0301],[5.905e+07,92.89,17.75,93.67,40.16,279,0.0045],[4.416e+07,96.46,4.81,89.9,47.14,251,0.0074],[4.773e+07,89.67,3.39,90.54,42.19,315,0.0206],[3.672e+07,89.8,16.5,92.31,51.81,283,0.0378],[3.283e+07,79.02,25.79,94.17,47.94,269,0.0108],[5.913e+07,97.62,11.99,95.4,52.51,237,0.032],[4.437e+07,88.78,23.6,88.56,48.62,303,0.0068],[5.037e+07,90.6,7.17,90.58,47.49,270,0.0055],[2.763e+07,88.41,2.91,92.81,45.91,317,0.0353],[5.507e+07,92.88,6.01,91.54,52.3,304,0.0001],[4.757e+07,95.73,10.26,93.11,47.71,265,0.0041],[2.642e+07,95.42,18.8,95.77,50.43,250,0.0384],[4.438e+07,99.5,6.25,86.2,42.67,255,0.0291],[3.068e+07,94.75,16.45,92.97,48.13,311,0.0038],[4.421e+07,88.42,10.6,91.53,49.74,314,0.0389],[3.732e+07,91.33,21.43,92.38,44.94,322,0.0081],[5.198e+07,93.95,8.86,93.36,49.68,241,0.039],[3.591e+07,89.48,24.07,92.25,40.83,224,0.0179],[4.384e+07,90.38,4.28,91.69,52.09,253,0.0174],[2.475e+07,94.05,14.02,91.33,54.14,263,0.0094],[3.553e+07,89.94,8.89,92.11,45.14,293,0.0274],[5.167e+07,89.7,11.8,90.25,46.59,305,0.0053],[4.027e+07,92.83,11.11,91.15,56.42,354,0.0109],[6.219e+07,94.15,18.98,92.54,48.46,221,0.0024],[2.313e+07,88.7,16.89,92.46,47.81,228,0.0362],[4.811e+07,93.37,27.16,92.35,48.63,149,0.0185],[3.604e+07,95.84,8.99,92.94,46.56,257,0.016],[5.198e+07,97.33,17.13,96.02,40.34,234,0.0025],[3.944e+07,88.95,10.68,90.99,50.1,308,0.0087],[3.375e+07,93.43,5.63,94.53,48.28,254,0.0056],[4.563e+07,96.44,11.56,91.44,48.23,305,0.0189],[3.927e+07,91.57,11.44,90.43,49.61,265,0.0178],[4.36e+07,99.05,10.52,88.77,42.68,265,0.0084],[2.632e+07,88.1,20,94.59,51.26,248,0.0005],[5.083e+07,96.17,11.95,88.6,48.08,226,0.0045],[4.076e+07,94.36,22.35,91.5,46.36,344,0.0143],[4.732e+07,96.26,10.22,89.31,48.72,328,0.0063],[4.337e+07,95.62,15.79,90.51,55.74,262,0.0171],[4.011e+07,99.5,6.46,91.48,45.43,245,0.0088],[2.234e+07,95.3,8.38,87.6,47.46,267,0.0149],[3.476e+07,92.38,6.17,90.16,53.23,265,0.0312],[5.16e+07,94.24,21.01,89.15,43.77,272,0.0307],[4.327e+07,96.49,11.69,92.55,46.85,323,0.0271],[3.411e+07,92.97,4.57,88.51,51.67,280,0.0074],[4.405e+07,83.22,22.92,95.37,46.89,253,0.0229],[3.211e+07,91.49,18.3,90.97,49.17,322,0.0128],[2.981e+07,95.74,12.41,92.73,51.25,294,0.0013],[4.704e+07,82.17,31.35,89.37,46.99,258,0.0297],[2.963e+07,85.39,31.62,95.75,49.92,272,0.0367],[4.766e+07,99.5,8.65,93.12,49.15,235,0.0013],[3.302e+07,93.63,15.27,91.9,40.33,313,0.0298],[5.07e+07,92.5,15.47,86.82,46.62,263,0.0188],[3.702e+07,92.23,7.66,92.26,53.15,303,0.0268],[4.853e+07,92.78,22.69,90.51,45.75,237,0.0224],[4.213e+07,88.49,12.67,89.46,53.53,264,0.0102],[4.837e+07,93.46,6.95,93.15,52.82,301,0.0357],[4.408e+07,93.74,10.84,94.33,49.12,272,0.0077],[3.07e+07,95.42,20.6,90.54,48.28,317,0.0098],[3.482e+07,92.11,12.25,93.58,49.7,285,0.0129],[3.033e+07,81.72,21.48,89.96,50.38,198,0.0066],[3.506e+07,96.86,10.9,91.12,52.24,321,0.0274],[3.874e+07,93.97,12.2,91.9,46.75,306,0.0249],[5.189e+07,91.75,20.37,93.02,47.86,308,0.0172],[4.897e+07,91.86,15.16,93.14,43.43,366,0.0095],[5.329e+07,93.5,8.04,93.6,49.02,274,0.0225],[4.984e+07,96.54,14.74,93.72,50.56,312,0.0286],[4.63e+07,90.68,13.94,92.06,49.18,263,0.0135],[6.972e+07,94.67,15.69,91.37,51.37,229,0.0342],[5.177e+07,91.97,4.04,95.67,49.45,235,0.0243],[3.182e+07,90.59,19.49,92.53,48.97,290,0.0325],[3.837e+07,93.75,5.95,93.5,48.33,282,0.0005],[3.702e+07,92.84,19.93,96.06,51.7,268,0.0286],[5.42e+07,91.71,11.97,91.38,50.06,274,0.0325],[3.724e+07,93.17,19.11,94.41,52.82,258,0.0106],[4.444e+07,93.16,20.34,90.74,45.25,275,0.0062],[5.108e+07,94.13,26.21,94.33,49.79,272,0.0166],[3.017e+07,88.6,22.03,91.89,50.98,267,0.0196],[4.906e+07,96.15,15.06,91.21,49.33,288,0.0292],[5.342e+07,88.31,15.27,93.49,44.19,335,0.0203],[4.472e+07,93.47,15,90.28,49.4,217,0.0136]]},"x":null,"z":{"Lane":["L4","L5","L4","L1","L4","L7","L7","L4","L5","L7","L3","L1","L2","L1","L1","L3","L8","L2","L6","L8","L3","L5","L6","L8","L6","L2","L2","L4","L6","L8","L2","L1","L4","L1","L4","L4","L5","L7","L8","L8","L7","L6","L5","L8","L6","L5","L4","L1","L5","L5","L8","L7","L5","L5","L6","L8","L4","L1","L7","L7","L3","L7","L5","L3","L3","L8","L1","L7","L6","L4","L1","L8","L6","L5","L5","L3","L4","L7","L7","L2","L7","L1","L7","L8","L2","L2","L4","L5","L6","L2","L1","L8","L3","L2","L4","L8"],"Batch":["RunA","RunC","RunA","RunC","RunC","RunA","RunB","RunB","RunB","RunC","RunC","RunC","RunB","RunA","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunB","RunC","RunA","RunA","RunC","RunA","RunC","RunC","RunC","RunA","RunB","RunA","RunC","RunB","RunB","RunC","RunA","RunA","RunA","RunB","RunA","RunA","RunB","RunA","RunA","RunB","RunA","RunC","RunC","RunA","RunC","RunC","RunA","RunA","RunC","RunA","RunB","RunA","RunB","RunC","RunB","RunB","RunB","RunB","RunC","RunB","RunB","RunA","RunA","RunC","RunB","RunA","RunB","RunA","RunB","RunC","RunC","RunA","RunA","RunA","RunC","RunA","RunC","RunC","RunA","RunA","RunA","RunB","RunC","RunA","RunC","RunC"],"Library":["PolyA","RiboZero","RiboZero","PolyA","RiboZero","PolyA","RiboZero","RiboZero","Exome","PolyA","PolyA","RiboZero","Exome","RiboZero","RiboZero","RiboZero","Exome","RiboZero","PolyA","PolyA","Exome","RiboZero","RiboZero","RiboZero","RiboZero","RiboZero","RiboZero","Exome","PolyA","PolyA","Exome","RiboZero","Exome","PolyA","Exome","PolyA","PolyA","PolyA","RiboZero","RiboZero","RiboZero","RiboZero","Exome","PolyA","RiboZero","PolyA","Exome","Exome","PolyA","RiboZero","RiboZero","Exome","Exome","RiboZero","PolyA","Exome","PolyA","RiboZero","RiboZero","PolyA","RiboZero","Exome","RiboZero","PolyA","Exome","Exome","Exome","RiboZero","RiboZero","PolyA","RiboZero","Exome","Exome","RiboZero","PolyA","PolyA","PolyA","PolyA","PolyA","Exome","RiboZero","RiboZero","PolyA","Exome","PolyA","RiboZero","RiboZero","PolyA","RiboZero","RiboZero","RiboZero","Exome","PolyA","PolyA","Exome","Exome"]}},"config":{"graphType":"Scatter2D","isR":true,"broadcast":true,"broadcastGroup":"qc","xAxis":["pct_duplication"],"yAxis":["pct_mapped"],"colorBy":"Batch","sizeBy":"total_reads","title":"Mapping rate vs duplication — select the bottom-right"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
</section>
<section id="contamination-vs-mapping" class="level3">
<h3 class="anchored" data-anchor-id="contamination-vs-mapping">2 — Contamination vs mapping</h3>
<div class="cell">
<div class="sourceCode cell-code" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb6-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qc_panel</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xAxis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_mapped"</span>),</span>
<span id="cb6-2">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yAxis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"contamination_freemix"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colorBy =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span>,</span>
<span id="cb6-3">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Contamination (freemix) vs mapping rate"</span>),</span>
<span id="cb6-4">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">640</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">360</span>)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-c05435084398fcea9ffd" style="width:100%;height:365px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-c05435084398fcea9ffd">{"x":{"data":{"y":{"vars":["S001","S002","S003","S004","S005","S006","S007","S008","S009","S010","S011","S012","S013","S014","S015","S016","S017","S018","S019","S020","S021","S022","S023","S024","S025","S026","S027","S028","S029","S030","S031","S032","S033","S034","S035","S036","S037","S038","S039","S040","S041","S042","S043","S044","S045","S046","S047","S048","S049","S050","S051","S052","S053","S054","S055","S056","S057","S058","S059","S060","S061","S062","S063","S064","S065","S066","S067","S068","S069","S070","S071","S072","S073","S074","S075","S076","S077","S078","S079","S080","S081","S082","S083","S084","S085","S086","S087","S088","S089","S090","S091","S092","S093","S094","S095","S096"],"smps":["total_reads","pct_mapped","pct_duplication","pct_q30","gc_content","insert_size","contamination_freemix"],"data":[[3.973e+07,93.85,11.9,89.58,44.63,295,0.0165],[4.038e+07,86.82,13.41,94.49,46.71,280,0.0015],[3.258e+07,99.47,7.88,90.7,50.27,286,0.0205],[5.394e+07,97.33,13.95,93.02,44.51,296,0.0283],[4.472e+07,93.27,11.08,91.7,45.65,353,0.0344],[3.66e+07,93.81,13.99,91.47,46.64,307,0.0252],[4.61e+07,96.7,19.76,91.54,48.13,200,0.0377],[4.8e+07,95.26,18.89,92.35,48.73,253,0.0274],[3.637e+07,96.45,13.29,92.15,53.85,276,0.0037],[5.097e+07,98.24,29.2,90.22,45.15,312,0.0363],[3.36e+07,90.06,14.99,87.9,45.15,307,0.0214],[4.866e+07,90.39,24.5,92.59,48.25,288,0.0286],[4.943e+07,92.61,11.81,91.74,44.08,308,0.0104],[4.712e+07,90.14,10.41,91.39,47.9,240,0.0185],[4.685e+07,97.07,5.44,90.31,42.56,246,0.005],[4.16e+07,86.13,23.03,94.13,52.31,195,0.0301],[5.905e+07,92.89,17.75,93.67,40.16,279,0.0045],[4.416e+07,96.46,4.81,89.9,47.14,251,0.0074],[4.773e+07,89.67,3.39,90.54,42.19,315,0.0206],[3.672e+07,89.8,16.5,92.31,51.81,283,0.0378],[3.283e+07,79.02,25.79,94.17,47.94,269,0.0108],[5.913e+07,97.62,11.99,95.4,52.51,237,0.032],[4.437e+07,88.78,23.6,88.56,48.62,303,0.0068],[5.037e+07,90.6,7.17,90.58,47.49,270,0.0055],[2.763e+07,88.41,2.91,92.81,45.91,317,0.0353],[5.507e+07,92.88,6.01,91.54,52.3,304,0.0001],[4.757e+07,95.73,10.26,93.11,47.71,265,0.0041],[2.642e+07,95.42,18.8,95.77,50.43,250,0.0384],[4.438e+07,99.5,6.25,86.2,42.67,255,0.0291],[3.068e+07,94.75,16.45,92.97,48.13,311,0.0038],[4.421e+07,88.42,10.6,91.53,49.74,314,0.0389],[3.732e+07,91.33,21.43,92.38,44.94,322,0.0081],[5.198e+07,93.95,8.86,93.36,49.68,241,0.039],[3.591e+07,89.48,24.07,92.25,40.83,224,0.0179],[4.384e+07,90.38,4.28,91.69,52.09,253,0.0174],[2.475e+07,94.05,14.02,91.33,54.14,263,0.0094],[3.553e+07,89.94,8.89,92.11,45.14,293,0.0274],[5.167e+07,89.7,11.8,90.25,46.59,305,0.0053],[4.027e+07,92.83,11.11,91.15,56.42,354,0.0109],[6.219e+07,94.15,18.98,92.54,48.46,221,0.0024],[2.313e+07,88.7,16.89,92.46,47.81,228,0.0362],[4.811e+07,93.37,27.16,92.35,48.63,149,0.0185],[3.604e+07,95.84,8.99,92.94,46.56,257,0.016],[5.198e+07,97.33,17.13,96.02,40.34,234,0.0025],[3.944e+07,88.95,10.68,90.99,50.1,308,0.0087],[3.375e+07,93.43,5.63,94.53,48.28,254,0.0056],[4.563e+07,96.44,11.56,91.44,48.23,305,0.0189],[3.927e+07,91.57,11.44,90.43,49.61,265,0.0178],[4.36e+07,99.05,10.52,88.77,42.68,265,0.0084],[2.632e+07,88.1,20,94.59,51.26,248,0.0005],[5.083e+07,96.17,11.95,88.6,48.08,226,0.0045],[4.076e+07,94.36,22.35,91.5,46.36,344,0.0143],[4.732e+07,96.26,10.22,89.31,48.72,328,0.0063],[4.337e+07,95.62,15.79,90.51,55.74,262,0.0171],[4.011e+07,99.5,6.46,91.48,45.43,245,0.0088],[2.234e+07,95.3,8.38,87.6,47.46,267,0.0149],[3.476e+07,92.38,6.17,90.16,53.23,265,0.0312],[5.16e+07,94.24,21.01,89.15,43.77,272,0.0307],[4.327e+07,96.49,11.69,92.55,46.85,323,0.0271],[3.411e+07,92.97,4.57,88.51,51.67,280,0.0074],[4.405e+07,83.22,22.92,95.37,46.89,253,0.0229],[3.211e+07,91.49,18.3,90.97,49.17,322,0.0128],[2.981e+07,95.74,12.41,92.73,51.25,294,0.0013],[4.704e+07,82.17,31.35,89.37,46.99,258,0.0297],[2.963e+07,85.39,31.62,95.75,49.92,272,0.0367],[4.766e+07,99.5,8.65,93.12,49.15,235,0.0013],[3.302e+07,93.63,15.27,91.9,40.33,313,0.0298],[5.07e+07,92.5,15.47,86.82,46.62,263,0.0188],[3.702e+07,92.23,7.66,92.26,53.15,303,0.0268],[4.853e+07,92.78,22.69,90.51,45.75,237,0.0224],[4.213e+07,88.49,12.67,89.46,53.53,264,0.0102],[4.837e+07,93.46,6.95,93.15,52.82,301,0.0357],[4.408e+07,93.74,10.84,94.33,49.12,272,0.0077],[3.07e+07,95.42,20.6,90.54,48.28,317,0.0098],[3.482e+07,92.11,12.25,93.58,49.7,285,0.0129],[3.033e+07,81.72,21.48,89.96,50.38,198,0.0066],[3.506e+07,96.86,10.9,91.12,52.24,321,0.0274],[3.874e+07,93.97,12.2,91.9,46.75,306,0.0249],[5.189e+07,91.75,20.37,93.02,47.86,308,0.0172],[4.897e+07,91.86,15.16,93.14,43.43,366,0.0095],[5.329e+07,93.5,8.04,93.6,49.02,274,0.0225],[4.984e+07,96.54,14.74,93.72,50.56,312,0.0286],[4.63e+07,90.68,13.94,92.06,49.18,263,0.0135],[6.972e+07,94.67,15.69,91.37,51.37,229,0.0342],[5.177e+07,91.97,4.04,95.67,49.45,235,0.0243],[3.182e+07,90.59,19.49,92.53,48.97,290,0.0325],[3.837e+07,93.75,5.95,93.5,48.33,282,0.0005],[3.702e+07,92.84,19.93,96.06,51.7,268,0.0286],[5.42e+07,91.71,11.97,91.38,50.06,274,0.0325],[3.724e+07,93.17,19.11,94.41,52.82,258,0.0106],[4.444e+07,93.16,20.34,90.74,45.25,275,0.0062],[5.108e+07,94.13,26.21,94.33,49.79,272,0.0166],[3.017e+07,88.6,22.03,91.89,50.98,267,0.0196],[4.906e+07,96.15,15.06,91.21,49.33,288,0.0292],[5.342e+07,88.31,15.27,93.49,44.19,335,0.0203],[4.472e+07,93.47,15,90.28,49.4,217,0.0136]]},"x":null,"z":{"Lane":["L4","L5","L4","L1","L4","L7","L7","L4","L5","L7","L3","L1","L2","L1","L1","L3","L8","L2","L6","L8","L3","L5","L6","L8","L6","L2","L2","L4","L6","L8","L2","L1","L4","L1","L4","L4","L5","L7","L8","L8","L7","L6","L5","L8","L6","L5","L4","L1","L5","L5","L8","L7","L5","L5","L6","L8","L4","L1","L7","L7","L3","L7","L5","L3","L3","L8","L1","L7","L6","L4","L1","L8","L6","L5","L5","L3","L4","L7","L7","L2","L7","L1","L7","L8","L2","L2","L4","L5","L6","L2","L1","L8","L3","L2","L4","L8"],"Batch":["RunA","RunC","RunA","RunC","RunC","RunA","RunB","RunB","RunB","RunC","RunC","RunC","RunB","RunA","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunB","RunC","RunA","RunA","RunC","RunA","RunC","RunC","RunC","RunA","RunB","RunA","RunC","RunB","RunB","RunC","RunA","RunA","RunA","RunB","RunA","RunA","RunB","RunA","RunA","RunB","RunA","RunC","RunC","RunA","RunC","RunC","RunA","RunA","RunC","RunA","RunB","RunA","RunB","RunC","RunB","RunB","RunB","RunB","RunC","RunB","RunB","RunA","RunA","RunC","RunB","RunA","RunB","RunA","RunB","RunC","RunC","RunA","RunA","RunA","RunC","RunA","RunC","RunC","RunA","RunA","RunA","RunB","RunC","RunA","RunC","RunC"],"Library":["PolyA","RiboZero","RiboZero","PolyA","RiboZero","PolyA","RiboZero","RiboZero","Exome","PolyA","PolyA","RiboZero","Exome","RiboZero","RiboZero","RiboZero","Exome","RiboZero","PolyA","PolyA","Exome","RiboZero","RiboZero","RiboZero","RiboZero","RiboZero","RiboZero","Exome","PolyA","PolyA","Exome","RiboZero","Exome","PolyA","Exome","PolyA","PolyA","PolyA","RiboZero","RiboZero","RiboZero","RiboZero","Exome","PolyA","RiboZero","PolyA","Exome","Exome","PolyA","RiboZero","RiboZero","Exome","Exome","RiboZero","PolyA","Exome","PolyA","RiboZero","RiboZero","PolyA","RiboZero","Exome","RiboZero","PolyA","Exome","Exome","Exome","RiboZero","RiboZero","PolyA","RiboZero","Exome","Exome","RiboZero","PolyA","PolyA","PolyA","PolyA","PolyA","Exome","RiboZero","RiboZero","PolyA","Exome","PolyA","RiboZero","RiboZero","PolyA","RiboZero","RiboZero","RiboZero","Exome","PolyA","PolyA","Exome","Exome"]}},"config":{"graphType":"Scatter2D","isR":true,"broadcast":true,"broadcastGroup":"qc","xAxis":["pct_mapped"],"yAxis":["contamination_freemix"],"colorBy":"Batch","title":"Contamination (freemix) vs mapping rate"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
</section>
<section id="q30-vs-gc-by-library-prep" class="level3">
<h3 class="anchored" data-anchor-id="q30-vs-gc-by-library-prep">3 — Q30 vs GC, by library prep</h3>
<div class="cell">
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qc_panel</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Scatter2D"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xAxis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"gc_content"</span>),</span>
<span id="cb7-2">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">yAxis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"pct_q30"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colorBy =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Library"</span>,</span>
<span id="cb7-3">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Q30 vs GC content, coloured by library"</span>),</span>
<span id="cb7-4">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">640</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">360</span>)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-a9110a1bb34964137bfe" style="width:100%;height:365px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-a9110a1bb34964137bfe">{"x":{"data":{"y":{"vars":["S001","S002","S003","S004","S005","S006","S007","S008","S009","S010","S011","S012","S013","S014","S015","S016","S017","S018","S019","S020","S021","S022","S023","S024","S025","S026","S027","S028","S029","S030","S031","S032","S033","S034","S035","S036","S037","S038","S039","S040","S041","S042","S043","S044","S045","S046","S047","S048","S049","S050","S051","S052","S053","S054","S055","S056","S057","S058","S059","S060","S061","S062","S063","S064","S065","S066","S067","S068","S069","S070","S071","S072","S073","S074","S075","S076","S077","S078","S079","S080","S081","S082","S083","S084","S085","S086","S087","S088","S089","S090","S091","S092","S093","S094","S095","S096"],"smps":["total_reads","pct_mapped","pct_duplication","pct_q30","gc_content","insert_size","contamination_freemix"],"data":[[3.973e+07,93.85,11.9,89.58,44.63,295,0.0165],[4.038e+07,86.82,13.41,94.49,46.71,280,0.0015],[3.258e+07,99.47,7.88,90.7,50.27,286,0.0205],[5.394e+07,97.33,13.95,93.02,44.51,296,0.0283],[4.472e+07,93.27,11.08,91.7,45.65,353,0.0344],[3.66e+07,93.81,13.99,91.47,46.64,307,0.0252],[4.61e+07,96.7,19.76,91.54,48.13,200,0.0377],[4.8e+07,95.26,18.89,92.35,48.73,253,0.0274],[3.637e+07,96.45,13.29,92.15,53.85,276,0.0037],[5.097e+07,98.24,29.2,90.22,45.15,312,0.0363],[3.36e+07,90.06,14.99,87.9,45.15,307,0.0214],[4.866e+07,90.39,24.5,92.59,48.25,288,0.0286],[4.943e+07,92.61,11.81,91.74,44.08,308,0.0104],[4.712e+07,90.14,10.41,91.39,47.9,240,0.0185],[4.685e+07,97.07,5.44,90.31,42.56,246,0.005],[4.16e+07,86.13,23.03,94.13,52.31,195,0.0301],[5.905e+07,92.89,17.75,93.67,40.16,279,0.0045],[4.416e+07,96.46,4.81,89.9,47.14,251,0.0074],[4.773e+07,89.67,3.39,90.54,42.19,315,0.0206],[3.672e+07,89.8,16.5,92.31,51.81,283,0.0378],[3.283e+07,79.02,25.79,94.17,47.94,269,0.0108],[5.913e+07,97.62,11.99,95.4,52.51,237,0.032],[4.437e+07,88.78,23.6,88.56,48.62,303,0.0068],[5.037e+07,90.6,7.17,90.58,47.49,270,0.0055],[2.763e+07,88.41,2.91,92.81,45.91,317,0.0353],[5.507e+07,92.88,6.01,91.54,52.3,304,0.0001],[4.757e+07,95.73,10.26,93.11,47.71,265,0.0041],[2.642e+07,95.42,18.8,95.77,50.43,250,0.0384],[4.438e+07,99.5,6.25,86.2,42.67,255,0.0291],[3.068e+07,94.75,16.45,92.97,48.13,311,0.0038],[4.421e+07,88.42,10.6,91.53,49.74,314,0.0389],[3.732e+07,91.33,21.43,92.38,44.94,322,0.0081],[5.198e+07,93.95,8.86,93.36,49.68,241,0.039],[3.591e+07,89.48,24.07,92.25,40.83,224,0.0179],[4.384e+07,90.38,4.28,91.69,52.09,253,0.0174],[2.475e+07,94.05,14.02,91.33,54.14,263,0.0094],[3.553e+07,89.94,8.89,92.11,45.14,293,0.0274],[5.167e+07,89.7,11.8,90.25,46.59,305,0.0053],[4.027e+07,92.83,11.11,91.15,56.42,354,0.0109],[6.219e+07,94.15,18.98,92.54,48.46,221,0.0024],[2.313e+07,88.7,16.89,92.46,47.81,228,0.0362],[4.811e+07,93.37,27.16,92.35,48.63,149,0.0185],[3.604e+07,95.84,8.99,92.94,46.56,257,0.016],[5.198e+07,97.33,17.13,96.02,40.34,234,0.0025],[3.944e+07,88.95,10.68,90.99,50.1,308,0.0087],[3.375e+07,93.43,5.63,94.53,48.28,254,0.0056],[4.563e+07,96.44,11.56,91.44,48.23,305,0.0189],[3.927e+07,91.57,11.44,90.43,49.61,265,0.0178],[4.36e+07,99.05,10.52,88.77,42.68,265,0.0084],[2.632e+07,88.1,20,94.59,51.26,248,0.0005],[5.083e+07,96.17,11.95,88.6,48.08,226,0.0045],[4.076e+07,94.36,22.35,91.5,46.36,344,0.0143],[4.732e+07,96.26,10.22,89.31,48.72,328,0.0063],[4.337e+07,95.62,15.79,90.51,55.74,262,0.0171],[4.011e+07,99.5,6.46,91.48,45.43,245,0.0088],[2.234e+07,95.3,8.38,87.6,47.46,267,0.0149],[3.476e+07,92.38,6.17,90.16,53.23,265,0.0312],[5.16e+07,94.24,21.01,89.15,43.77,272,0.0307],[4.327e+07,96.49,11.69,92.55,46.85,323,0.0271],[3.411e+07,92.97,4.57,88.51,51.67,280,0.0074],[4.405e+07,83.22,22.92,95.37,46.89,253,0.0229],[3.211e+07,91.49,18.3,90.97,49.17,322,0.0128],[2.981e+07,95.74,12.41,92.73,51.25,294,0.0013],[4.704e+07,82.17,31.35,89.37,46.99,258,0.0297],[2.963e+07,85.39,31.62,95.75,49.92,272,0.0367],[4.766e+07,99.5,8.65,93.12,49.15,235,0.0013],[3.302e+07,93.63,15.27,91.9,40.33,313,0.0298],[5.07e+07,92.5,15.47,86.82,46.62,263,0.0188],[3.702e+07,92.23,7.66,92.26,53.15,303,0.0268],[4.853e+07,92.78,22.69,90.51,45.75,237,0.0224],[4.213e+07,88.49,12.67,89.46,53.53,264,0.0102],[4.837e+07,93.46,6.95,93.15,52.82,301,0.0357],[4.408e+07,93.74,10.84,94.33,49.12,272,0.0077],[3.07e+07,95.42,20.6,90.54,48.28,317,0.0098],[3.482e+07,92.11,12.25,93.58,49.7,285,0.0129],[3.033e+07,81.72,21.48,89.96,50.38,198,0.0066],[3.506e+07,96.86,10.9,91.12,52.24,321,0.0274],[3.874e+07,93.97,12.2,91.9,46.75,306,0.0249],[5.189e+07,91.75,20.37,93.02,47.86,308,0.0172],[4.897e+07,91.86,15.16,93.14,43.43,366,0.0095],[5.329e+07,93.5,8.04,93.6,49.02,274,0.0225],[4.984e+07,96.54,14.74,93.72,50.56,312,0.0286],[4.63e+07,90.68,13.94,92.06,49.18,263,0.0135],[6.972e+07,94.67,15.69,91.37,51.37,229,0.0342],[5.177e+07,91.97,4.04,95.67,49.45,235,0.0243],[3.182e+07,90.59,19.49,92.53,48.97,290,0.0325],[3.837e+07,93.75,5.95,93.5,48.33,282,0.0005],[3.702e+07,92.84,19.93,96.06,51.7,268,0.0286],[5.42e+07,91.71,11.97,91.38,50.06,274,0.0325],[3.724e+07,93.17,19.11,94.41,52.82,258,0.0106],[4.444e+07,93.16,20.34,90.74,45.25,275,0.0062],[5.108e+07,94.13,26.21,94.33,49.79,272,0.0166],[3.017e+07,88.6,22.03,91.89,50.98,267,0.0196],[4.906e+07,96.15,15.06,91.21,49.33,288,0.0292],[5.342e+07,88.31,15.27,93.49,44.19,335,0.0203],[4.472e+07,93.47,15,90.28,49.4,217,0.0136]]},"x":null,"z":{"Lane":["L4","L5","L4","L1","L4","L7","L7","L4","L5","L7","L3","L1","L2","L1","L1","L3","L8","L2","L6","L8","L3","L5","L6","L8","L6","L2","L2","L4","L6","L8","L2","L1","L4","L1","L4","L4","L5","L7","L8","L8","L7","L6","L5","L8","L6","L5","L4","L1","L5","L5","L8","L7","L5","L5","L6","L8","L4","L1","L7","L7","L3","L7","L5","L3","L3","L8","L1","L7","L6","L4","L1","L8","L6","L5","L5","L3","L4","L7","L7","L2","L7","L1","L7","L8","L2","L2","L4","L5","L6","L2","L1","L8","L3","L2","L4","L8"],"Batch":["RunA","RunC","RunA","RunC","RunC","RunA","RunB","RunB","RunB","RunC","RunC","RunC","RunB","RunA","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunB","RunC","RunA","RunA","RunC","RunA","RunC","RunC","RunC","RunA","RunB","RunA","RunC","RunB","RunB","RunC","RunA","RunA","RunA","RunB","RunA","RunA","RunB","RunA","RunA","RunB","RunA","RunC","RunC","RunA","RunC","RunC","RunA","RunA","RunC","RunA","RunB","RunA","RunB","RunC","RunB","RunB","RunB","RunB","RunC","RunB","RunB","RunA","RunA","RunC","RunB","RunA","RunB","RunA","RunB","RunC","RunC","RunA","RunA","RunA","RunC","RunA","RunC","RunC","RunA","RunA","RunA","RunB","RunC","RunA","RunC","RunC"],"Library":["PolyA","RiboZero","RiboZero","PolyA","RiboZero","PolyA","RiboZero","RiboZero","Exome","PolyA","PolyA","RiboZero","Exome","RiboZero","RiboZero","RiboZero","Exome","RiboZero","PolyA","PolyA","Exome","RiboZero","RiboZero","RiboZero","RiboZero","RiboZero","RiboZero","Exome","PolyA","PolyA","Exome","RiboZero","Exome","PolyA","Exome","PolyA","PolyA","PolyA","RiboZero","RiboZero","RiboZero","RiboZero","Exome","PolyA","RiboZero","PolyA","Exome","Exome","PolyA","RiboZero","RiboZero","Exome","Exome","RiboZero","PolyA","Exome","PolyA","RiboZero","RiboZero","PolyA","RiboZero","Exome","RiboZero","PolyA","Exome","Exome","Exome","RiboZero","RiboZero","PolyA","RiboZero","Exome","Exome","RiboZero","PolyA","PolyA","PolyA","PolyA","PolyA","Exome","RiboZero","RiboZero","PolyA","Exome","PolyA","RiboZero","RiboZero","PolyA","RiboZero","RiboZero","RiboZero","Exome","PolyA","PolyA","Exome","Exome"]}},"config":{"graphType":"Scatter2D","isR":true,"broadcast":true,"broadcastGroup":"qc","xAxis":["gc_content"],"yAxis":["pct_q30"],"colorBy":"Library","title":"Q30 vs GC content, coloured by library"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
</section>
<section id="sequencing-depth-per-sample" class="level3">
<h3 class="anchored" data-anchor-id="sequencing-depth-per-sample">4 — Sequencing depth per sample</h3>
<div class="cell">
<div class="sourceCode cell-code" id="cb8" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb8-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">qc_panel</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Bar"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphOrientation =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vertical"</span>,</span>
<span id="cb8-2">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xAxis =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"total_reads"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colorBy =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Batch"</span>,</span>
<span id="cb8-3">              <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Total reads per sample (flag the short ones)"</span>),</span>
<span id="cb8-4">         <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">820</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">300</span>)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-e3f3b3288326da57f797" style="width:100%;height:237px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-e3f3b3288326da57f797">{"x":{"data":{"y":{"vars":["S001","S002","S003","S004","S005","S006","S007","S008","S009","S010","S011","S012","S013","S014","S015","S016","S017","S018","S019","S020","S021","S022","S023","S024","S025","S026","S027","S028","S029","S030","S031","S032","S033","S034","S035","S036","S037","S038","S039","S040","S041","S042","S043","S044","S045","S046","S047","S048","S049","S050","S051","S052","S053","S054","S055","S056","S057","S058","S059","S060","S061","S062","S063","S064","S065","S066","S067","S068","S069","S070","S071","S072","S073","S074","S075","S076","S077","S078","S079","S080","S081","S082","S083","S084","S085","S086","S087","S088","S089","S090","S091","S092","S093","S094","S095","S096"],"smps":["total_reads","pct_mapped","pct_duplication","pct_q30","gc_content","insert_size","contamination_freemix"],"data":[[3.973e+07,93.85,11.9,89.58,44.63,295,0.0165],[4.038e+07,86.82,13.41,94.49,46.71,280,0.0015],[3.258e+07,99.47,7.88,90.7,50.27,286,0.0205],[5.394e+07,97.33,13.95,93.02,44.51,296,0.0283],[4.472e+07,93.27,11.08,91.7,45.65,353,0.0344],[3.66e+07,93.81,13.99,91.47,46.64,307,0.0252],[4.61e+07,96.7,19.76,91.54,48.13,200,0.0377],[4.8e+07,95.26,18.89,92.35,48.73,253,0.0274],[3.637e+07,96.45,13.29,92.15,53.85,276,0.0037],[5.097e+07,98.24,29.2,90.22,45.15,312,0.0363],[3.36e+07,90.06,14.99,87.9,45.15,307,0.0214],[4.866e+07,90.39,24.5,92.59,48.25,288,0.0286],[4.943e+07,92.61,11.81,91.74,44.08,308,0.0104],[4.712e+07,90.14,10.41,91.39,47.9,240,0.0185],[4.685e+07,97.07,5.44,90.31,42.56,246,0.005],[4.16e+07,86.13,23.03,94.13,52.31,195,0.0301],[5.905e+07,92.89,17.75,93.67,40.16,279,0.0045],[4.416e+07,96.46,4.81,89.9,47.14,251,0.0074],[4.773e+07,89.67,3.39,90.54,42.19,315,0.0206],[3.672e+07,89.8,16.5,92.31,51.81,283,0.0378],[3.283e+07,79.02,25.79,94.17,47.94,269,0.0108],[5.913e+07,97.62,11.99,95.4,52.51,237,0.032],[4.437e+07,88.78,23.6,88.56,48.62,303,0.0068],[5.037e+07,90.6,7.17,90.58,47.49,270,0.0055],[2.763e+07,88.41,2.91,92.81,45.91,317,0.0353],[5.507e+07,92.88,6.01,91.54,52.3,304,0.0001],[4.757e+07,95.73,10.26,93.11,47.71,265,0.0041],[2.642e+07,95.42,18.8,95.77,50.43,250,0.0384],[4.438e+07,99.5,6.25,86.2,42.67,255,0.0291],[3.068e+07,94.75,16.45,92.97,48.13,311,0.0038],[4.421e+07,88.42,10.6,91.53,49.74,314,0.0389],[3.732e+07,91.33,21.43,92.38,44.94,322,0.0081],[5.198e+07,93.95,8.86,93.36,49.68,241,0.039],[3.591e+07,89.48,24.07,92.25,40.83,224,0.0179],[4.384e+07,90.38,4.28,91.69,52.09,253,0.0174],[2.475e+07,94.05,14.02,91.33,54.14,263,0.0094],[3.553e+07,89.94,8.89,92.11,45.14,293,0.0274],[5.167e+07,89.7,11.8,90.25,46.59,305,0.0053],[4.027e+07,92.83,11.11,91.15,56.42,354,0.0109],[6.219e+07,94.15,18.98,92.54,48.46,221,0.0024],[2.313e+07,88.7,16.89,92.46,47.81,228,0.0362],[4.811e+07,93.37,27.16,92.35,48.63,149,0.0185],[3.604e+07,95.84,8.99,92.94,46.56,257,0.016],[5.198e+07,97.33,17.13,96.02,40.34,234,0.0025],[3.944e+07,88.95,10.68,90.99,50.1,308,0.0087],[3.375e+07,93.43,5.63,94.53,48.28,254,0.0056],[4.563e+07,96.44,11.56,91.44,48.23,305,0.0189],[3.927e+07,91.57,11.44,90.43,49.61,265,0.0178],[4.36e+07,99.05,10.52,88.77,42.68,265,0.0084],[2.632e+07,88.1,20,94.59,51.26,248,0.0005],[5.083e+07,96.17,11.95,88.6,48.08,226,0.0045],[4.076e+07,94.36,22.35,91.5,46.36,344,0.0143],[4.732e+07,96.26,10.22,89.31,48.72,328,0.0063],[4.337e+07,95.62,15.79,90.51,55.74,262,0.0171],[4.011e+07,99.5,6.46,91.48,45.43,245,0.0088],[2.234e+07,95.3,8.38,87.6,47.46,267,0.0149],[3.476e+07,92.38,6.17,90.16,53.23,265,0.0312],[5.16e+07,94.24,21.01,89.15,43.77,272,0.0307],[4.327e+07,96.49,11.69,92.55,46.85,323,0.0271],[3.411e+07,92.97,4.57,88.51,51.67,280,0.0074],[4.405e+07,83.22,22.92,95.37,46.89,253,0.0229],[3.211e+07,91.49,18.3,90.97,49.17,322,0.0128],[2.981e+07,95.74,12.41,92.73,51.25,294,0.0013],[4.704e+07,82.17,31.35,89.37,46.99,258,0.0297],[2.963e+07,85.39,31.62,95.75,49.92,272,0.0367],[4.766e+07,99.5,8.65,93.12,49.15,235,0.0013],[3.302e+07,93.63,15.27,91.9,40.33,313,0.0298],[5.07e+07,92.5,15.47,86.82,46.62,263,0.0188],[3.702e+07,92.23,7.66,92.26,53.15,303,0.0268],[4.853e+07,92.78,22.69,90.51,45.75,237,0.0224],[4.213e+07,88.49,12.67,89.46,53.53,264,0.0102],[4.837e+07,93.46,6.95,93.15,52.82,301,0.0357],[4.408e+07,93.74,10.84,94.33,49.12,272,0.0077],[3.07e+07,95.42,20.6,90.54,48.28,317,0.0098],[3.482e+07,92.11,12.25,93.58,49.7,285,0.0129],[3.033e+07,81.72,21.48,89.96,50.38,198,0.0066],[3.506e+07,96.86,10.9,91.12,52.24,321,0.0274],[3.874e+07,93.97,12.2,91.9,46.75,306,0.0249],[5.189e+07,91.75,20.37,93.02,47.86,308,0.0172],[4.897e+07,91.86,15.16,93.14,43.43,366,0.0095],[5.329e+07,93.5,8.04,93.6,49.02,274,0.0225],[4.984e+07,96.54,14.74,93.72,50.56,312,0.0286],[4.63e+07,90.68,13.94,92.06,49.18,263,0.0135],[6.972e+07,94.67,15.69,91.37,51.37,229,0.0342],[5.177e+07,91.97,4.04,95.67,49.45,235,0.0243],[3.182e+07,90.59,19.49,92.53,48.97,290,0.0325],[3.837e+07,93.75,5.95,93.5,48.33,282,0.0005],[3.702e+07,92.84,19.93,96.06,51.7,268,0.0286],[5.42e+07,91.71,11.97,91.38,50.06,274,0.0325],[3.724e+07,93.17,19.11,94.41,52.82,258,0.0106],[4.444e+07,93.16,20.34,90.74,45.25,275,0.0062],[5.108e+07,94.13,26.21,94.33,49.79,272,0.0166],[3.017e+07,88.6,22.03,91.89,50.98,267,0.0196],[4.906e+07,96.15,15.06,91.21,49.33,288,0.0292],[5.342e+07,88.31,15.27,93.49,44.19,335,0.0203],[4.472e+07,93.47,15,90.28,49.4,217,0.0136]]},"x":null,"z":{"Lane":["L4","L5","L4","L1","L4","L7","L7","L4","L5","L7","L3","L1","L2","L1","L1","L3","L8","L2","L6","L8","L3","L5","L6","L8","L6","L2","L2","L4","L6","L8","L2","L1","L4","L1","L4","L4","L5","L7","L8","L8","L7","L6","L5","L8","L6","L5","L4","L1","L5","L5","L8","L7","L5","L5","L6","L8","L4","L1","L7","L7","L3","L7","L5","L3","L3","L8","L1","L7","L6","L4","L1","L8","L6","L5","L5","L3","L4","L7","L7","L2","L7","L1","L7","L8","L2","L2","L4","L5","L6","L2","L1","L8","L3","L2","L4","L8"],"Batch":["RunA","RunC","RunA","RunC","RunC","RunA","RunB","RunB","RunB","RunC","RunC","RunC","RunB","RunA","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunC","RunB","RunC","RunA","RunA","RunC","RunA","RunC","RunC","RunC","RunA","RunB","RunA","RunC","RunB","RunB","RunC","RunA","RunA","RunA","RunB","RunA","RunA","RunB","RunA","RunA","RunB","RunA","RunC","RunC","RunA","RunC","RunC","RunA","RunA","RunC","RunA","RunB","RunA","RunB","RunC","RunB","RunB","RunB","RunB","RunC","RunB","RunB","RunA","RunA","RunC","RunB","RunA","RunB","RunA","RunB","RunC","RunC","RunA","RunA","RunA","RunC","RunA","RunC","RunC","RunA","RunA","RunA","RunB","RunC","RunA","RunC","RunC"],"Library":["PolyA","RiboZero","RiboZero","PolyA","RiboZero","PolyA","RiboZero","RiboZero","Exome","PolyA","PolyA","RiboZero","Exome","RiboZero","RiboZero","RiboZero","Exome","RiboZero","PolyA","PolyA","Exome","RiboZero","RiboZero","RiboZero","RiboZero","RiboZero","RiboZero","Exome","PolyA","PolyA","Exome","RiboZero","Exome","PolyA","Exome","PolyA","PolyA","PolyA","RiboZero","RiboZero","RiboZero","RiboZero","Exome","PolyA","RiboZero","PolyA","Exome","Exome","PolyA","RiboZero","RiboZero","Exome","Exome","RiboZero","PolyA","Exome","PolyA","RiboZero","RiboZero","PolyA","RiboZero","Exome","RiboZero","PolyA","Exome","Exome","Exome","RiboZero","RiboZero","PolyA","RiboZero","Exome","Exome","RiboZero","PolyA","PolyA","PolyA","PolyA","PolyA","Exome","RiboZero","RiboZero","PolyA","Exome","PolyA","RiboZero","RiboZero","PolyA","RiboZero","RiboZero","RiboZero","Exome","PolyA","PolyA","Exome","Exome"]}},"config":{"graphType":"Bar","isR":true,"broadcast":true,"broadcastGroup":"qc","graphOrientation":"vertical","xAxis":["total_reads"],"colorBy":"Batch","title":"Total reads per sample (flag the short ones)"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>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.</p>
</section>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>Each panel is a portable <code>data</code> + <code>config</code> spec; the cross-filter is just a shared <code>broadcastGroup</code>. The same specs reproduce the dashboard from Python or JavaScript, against the same <code>ngs-qc.csv</code>.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../network-graphs-in-r/">Interactive network graphs in R</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Package: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>R</category>
  <category>canvasXpress</category>
  <category>dashboard</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/r/linked-dashboards-in-r/</guid>
  <pubDate>Thu, 29 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/r/linked-dashboards-in-r/thumbnail.png" medium="image" type="image/png" height="110" width="144"/>
</item>
<item>
  <title>Genome browser tracks in R with canvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/r/genome-tracks-in-r/</link>
  <description><![CDATA[ 




<p>A genome browser view stacks <strong>tracks</strong> that share one coordinate axis: coverage, gene models, variants. In R this usually means <code>Gviz</code> or <code>ggbio</code>. Here we build an interactive, zoomable view with <a href="https://canvasxpress.org">canvasXpress</a> — and the whole thing is one portable spec.</p>
<section id="the-data-shape" class="level2">
<h2 class="anchored" data-anchor-id="the-data-shape">The data shape</h2>
<p>A Genome figure is a list of <strong>tracks</strong> that share one coordinate axis — each with a <code>type</code>. Real browser views stack several: here we build four — <strong>gene models</strong> (<code>box</code>, multi-exon, connected), <strong>coverage across three tissues</strong> (<code>bar</code>), an <strong>expression heatmap</strong> (<code>heatmap</code>), and <strong>variant markers</strong> (<code>triangle</code>).</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(canvasXpress)</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>)</span>
<span id="cb1-4"></span>
<span id="cb1-5"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Gene models: each gene is a set of exon [start, end] intervals, drawn connected.</span></span>
<span id="cb1-6">genes <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(j) {</span>
<span id="cb1-7">  start <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">120</span></span>
<span id="cb1-8">  exons <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(k) <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(start <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> k <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, start <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> k <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>))</span>
<span id="cb1-9">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"GENE"</span>, j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dir =</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (j <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">==</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>) <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"right"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"left"</span>,</span>
<span id="cb1-10">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(70,130,220)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outline =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(0,0,0)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> exons)</span>
<span id="cb1-11">})</span>
<span id="cb1-12"></span>
<span id="cb1-13"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Coverage and expression: one entry per binned position, three tissues each.</span></span>
<span id="cb1-14">offsets  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">50</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">21</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">22</span></span>
<span id="cb1-15">coverage <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(offsets), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i)</span>
<span id="cb1-16">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p"</span>, i), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">offset =</span> offsets[i],</span>
<span id="cb1-17">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))))</span>
<span id="cb1-18">express  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(offsets), <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i)</span>
<span id="cb1-19">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"p"</span>, i), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">offset =</span> offsets[i],</span>
<span id="cb1-20">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>))))</span>
<span id="cb1-21"></span>
<span id="cb1-22"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># Variants: point markers at genomic positions.</span></span>
<span id="cb1-23">snps <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(k)</span>
<span id="cb1-24">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">id =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rs"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1000</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> k), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">offset =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">45</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">520</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>),</span>
<span id="cb1-25">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(200,40,40)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outline =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(0,0,0)"</span>))</span>
<span id="cb1-26"></span>
<span id="cb1-27">genome <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">tracks =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(</span>
<span id="cb1-28">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genes (exon models)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"box"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">connect =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> genes),</span>
<span id="cb1-29">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Coverage — Heart / Liver / Kidney"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bar"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">120</span>,</span>
<span id="cb1-30">       <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">fill =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(80,80,200)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">outline =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(60,60,60)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> coverage),</span>
<span id="cb1-31">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expression (z-score)"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"heatmap"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">90</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> express),</span>
<span id="cb1-32">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">name =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"SNPs"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">type =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"triangle"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data =</span> snps)</span>
<span id="cb1-33">))</span></code></pre></div>
</div>
</section>
<section id="the-plot" class="level2">
<h2 class="anchored" data-anchor-id="the-plot">The plot</h2>
<p>The Genome graph type is passed through to the engine as-is; <code>featureStaggered</code> spreads crowded features so labels stay legible.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">canvasXpress</span>(</span>
<span id="cb2-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data            =</span> genome,</span>
<span id="cb2-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType       =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Genome"</span>,</span>
<span id="cb2-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">background       =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(245,245,245)"</span>,</span>
<span id="cb2-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">featureStaggered =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>,</span>
<span id="cb2-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title            =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Multi-track genome browser: genes, coverage, expression and variants"</span>,</span>
<span id="cb2-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width            =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">760</span>,</span>
<span id="cb2-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height           =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">520</span></span>
<span id="cb2-9">)</span></code></pre></div>
<div class="cell-output cell-output-stderr">
<pre><code>The Genome graphType is an advanced chart, data is passed as-is to the JS library</code></pre>
</div>
<div class="cell-output-display">
<div id="htmlwidget-8950278926928da8d023" style="width:100%;height:444px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-8950278926928da8d023">{"x":{"data":{"tracks":[{"name":"Genes (exon models)","type":"box","connect":true,"data":[{"id":"GENE1","dir":"right","fill":"rgb(70,130,220)","outline":"rgb(0,0,0)","data":[[40,58],[70,88]]},{"id":"GENE2","dir":"left","fill":"rgb(70,130,220)","outline":"rgb(0,0,0)","data":[[160,178],[190,208],[220,238]]},{"id":"GENE3","dir":"right","fill":"rgb(70,130,220)","outline":"rgb(0,0,0)","data":[[280,298],[310,328],[340,358],[370,388]]},{"id":"GENE4","dir":"left","fill":"rgb(70,130,220)","outline":"rgb(0,0,0)","data":[[400,418],[430,448],[460,478]]}]},{"name":"Coverage — Heart / Liver / Kidney","type":"bar","height":120,"fill":"rgb(80,80,200)","outline":"rgb(60,60,60)","data":[{"id":"p1","offset":50,"data":[38,15,27]},{"id":"p2","offset":72,"data":[17,15,44]},{"id":"p3","offset":94,"data":[9,36,12]},{"id":"p4","offset":116,"data":[44,16,16]},{"id":"p5","offset":138,"data":[25,23,32]},{"id":"p6","offset":160,"data":[19,29,13]},{"id":"p7","offset":182,"data":[22,17,18]},{"id":"p8","offset":204,"data":[36,30,10]},{"id":"p9","offset":226,"data":[44,15,17]},{"id":"p10","offset":248,"data":[11,40,26]},{"id":"p11","offset":270,"data":[45,33,14]},{"id":"p12","offset":292,"data":[8,16,12]},{"id":"p13","offset":314,"data":[13,38,43]},{"id":"p14","offset":336,"data":[21,16,10]},{"id":"p15","offset":358,"data":[11,19,24]},{"id":"p16","offset":380,"data":[43,45,40]},{"id":"p17","offset":402,"data":[20,9,9]},{"id":"p18","offset":424,"data":[31,14,17]},{"id":"p19","offset":446,"data":[45,26,40]},{"id":"p20","offset":468,"data":[17,9,18]},{"id":"p21","offset":490,"data":[33,11,23]},{"id":"p22","offset":512,"data":[13,30,14]}]},{"name":"Expression (z-score)","type":"heatmap","height":90,"data":[{"id":"p1","offset":50,"data":[0.92,-0.79,0.57]},{"id":"p2","offset":72,"data":[0.92,0.26,0.35]},{"id":"p3","offset":94,"data":[1.17,-0.48,-0.42]},{"id":"p4","offset":116,"data":[0.96,-1.29,0.19]},{"id":"p5","offset":138,"data":[-0.03,0.47,1.02]},{"id":"p6","offset":160,"data":[0.27,0.23,0.75]},{"id":"p7","offset":182,"data":[1.22,0.38,-0.99]},{"id":"p8","offset":204,"data":[-0.16,1.74,-0.35]},{"id":"p9","offset":226,"data":[0.6899999999999999,1.22,0.79]},{"id":"p10","offset":248,"data":[-0.01,0.22,-0.89]},{"id":"p11","offset":270,"data":[0.44,-0.89,-0.85]},{"id":"p12","offset":292,"data":[-0.99,-0.65,1.05]},{"id":"p13","offset":314,"data":[-0.39,-0.07000000000000001,-0.46]},{"id":"p14","offset":336,"data":[0.54,0.93,-0.21]},{"id":"p15","offset":358,"data":[0.62,-0.41,1.05]},{"id":"p16","offset":380,"data":[0.6,1.02,0.61]},{"id":"p17","offset":402,"data":[0.21,-1.9,-0.68]},{"id":"p18","offset":424,"data":[0.48,-0.46,-0.28]},{"id":"p19","offset":446,"data":[-0.41,1.62,-0.72]},{"id":"p20","offset":468,"data":[-0.45,0.01,0.22]},{"id":"p21","offset":490,"data":[0.19,-0.05,-1.5]},{"id":"p22","offset":512,"data":[0.37,0.52,-0.48]}]},{"name":"SNPs","type":"triangle","data":[{"id":"rs1000","offset":52,"fill":"rgb(200,40,40)","outline":"rgb(0,0,0)"},{"id":"rs1001","offset":158,"fill":"rgb(200,40,40)","outline":"rgb(0,0,0)"},{"id":"rs1002","offset":316,"fill":"rgb(200,40,40)","outline":"rgb(0,0,0)"},{"id":"rs1003","offset":387,"fill":"rgb(200,40,40)","outline":"rgb(0,0,0)"},{"id":"rs1004","offset":165,"fill":"rgb(200,40,40)","outline":"rgb(0,0,0)"},{"id":"rs1005","offset":50,"fill":"rgb(200,40,40)","outline":"rgb(0,0,0)"},{"id":"rs1006","offset":264,"fill":"rgb(200,40,40)","outline":"rgb(0,0,0)"},{"id":"rs1007","offset":252,"fill":"rgb(200,40,40)","outline":"rgb(0,0,0)"},{"id":"rs1008","offset":258,"fill":"rgb(200,40,40)","outline":"rgb(0,0,0)"}]}]},"config":{"graphType":"Genome","isR":true,"background":"rgb(245,245,245)","featureStaggered":true,"title":"Multi-track genome browser: genes, coverage, expression and variants"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>Scroll/drag to pan and zoom into a region; every track stays locked to the shared coordinate axis, so the gene models, coverage, expression and variants line up position-for-position. Swap each track for your own pileup, annotation and VCF-derived data.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The tracks and <code>config</code> <strong>are</strong> the figure — one portable spec that renders the identical browser view from Python or JavaScript, and can be validated and re-rendered later.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../network-graphs-in-r/">Interactive network graphs in R</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Package: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>R</category>
  <category>canvasXpress</category>
  <category>genome</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/r/genome-tracks-in-r/</guid>
  <pubDate>Thu, 29 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/r/genome-tracks-in-r/thumbnail.png" medium="image" type="image/png" height="272" width="144"/>
</item>
<item>
  <title>Oncoprints (mutation landscapes) in JavaScript with CanvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/js/oncoprint-in-javascript/</link>
  <description><![CDATA[ 




<p>An oncoprint is the standard way to show a <strong>mutation landscape</strong>: genes down one axis, tumours along the other, each cell stacking the alterations that gene carries in that sample — copy-number amplification/deletion plus mutation type. Building one in the browser from scratch is a lot of SVG and sorting logic. CanvasXpress is a JavaScript library at heart, so it’s a <code>Heatmap</code> with overlay matrices.</p>
<section id="load-the-library" class="level2">
<h2 class="anchored" data-anchor-id="load-the-library">Load the library</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb1-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">link</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> href</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> rel</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"stylesheet"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> src</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="the-markup-and-the-spec" class="level2">
<h2 class="anchored" data-anchor-id="the-markup-and-the-spec">The markup and the spec</h2>
<p>The base matrix is <code>data</code>; same-shaped <code>data2</code> (copy number) and <code>data3</code> (mutation) are the overlays, each cell a string like <code>"Amplification"</code>, <code>"Missense"</code>, or <code>""</code>.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb2-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"onco"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"820"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"440"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> genes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TP53"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"KRAS"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PIK3CA"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PTEN"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"EGFR"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BRAF"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"APC"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RB1"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NF1"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MYC"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CDKN2A"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ARID1A"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-4">      samples <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> CNA <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Amplification"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Deletion"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> MUT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Missense"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Nonsense"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Truncating"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-5">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>) samples<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"T"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">10</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">?</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"0"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-6">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pick</span>(a) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> a[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">floor</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span>)]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> }</span>
<span id="cb2-7"></span>
<span id="cb2-8">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> base <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> cna <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> mut <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-9">  genes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">forEach</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (g<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> gi) {</span>
<span id="cb2-10">    <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> rate <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">max</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> gi <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> genes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span>))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> b <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> c <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-11">    samples<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">forEach</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> () {</span>
<span id="cb2-12">      b<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>((<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-13">      c<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> rate <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">?</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pick</span>(CNA) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-14">      m<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> rate <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">?</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pick</span>(MUT) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-15">    })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-16">    base<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(b)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> cna<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(c)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> mut<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(m)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-17">  })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-18"></span>
<span id="cb2-19">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">y</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">vars</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> genes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">smps</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> samples<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> base<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> cna<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data3</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> mut } }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-20">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heatmap"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">oncoprintCNA</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data2"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">oncoprintMUT</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data3"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-21">                 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">overlaysThickness</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">xAxis</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> samples<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-22">                 <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mutation landscape: 12 genes across 28 tumours"</span> }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-23"></span>
<span id="cb2-24">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CanvasXpress</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"onco"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> config)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-25"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="live-result" class="level2">
<h2 class="anchored" data-anchor-id="live-result">Live result</h2>
<link href="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"></script>
<canvas id="oncoLive" width="820" height="440"></canvas>
<script>
(function () {
  function draw() {
    if (typeof CanvasXpress === "undefined") { return setTimeout(draw, 60); }
    var genes = ["TP53","KRAS","PIK3CA","PTEN","EGFR","BRAF","APC","RB1","NF1","MYC","CDKN2A","ARID1A"],
        samples = [], CNA = ["Amplification","Deletion"], MUT = ["Missense","Nonsense","Truncating"];
    for (var i = 0; i < 28; i++) samples.push("T" + (i + 1 < 10 ? "0" : "") + (i + 1));
    function pick(a) { return a[Math.floor(Math.random() * a.length)]; }
    var base = [], cna = [], mut = [];
    genes.forEach(function (g, gi) {
      var rate = Math.max(0.05, 0.5 * (1 - gi / genes.length)), b = [], c = [], m = [];
      samples.forEach(function () {
        b.push(Math.round((Math.random() * 4 - 2) * 100) / 100);
        c.push(Math.random() < rate * 0.5 ? pick(CNA) : "");
        m.push(Math.random() < rate ? pick(MUT) : "");
      });
      base.push(b); cna.push(c); mut.push(m);
    });
    new CanvasXpress("oncoLive",
      { y: { vars: genes, smps: samples, data: base, data2: cna, data3: mut } },
      { graphType: "Heatmap", oncoprintCNA: "data2", oncoprintMUT: "data3", overlaysThickness: 100,
        xAxis: samples, title: "Mutation landscape: 12 genes across 28 tumours" });
  }
  draw();
})();
</script>
<p>canvasXpress sorts the waterfall for you and shows the alteration frequency per row. Hover a cell to read the exact alteration; swap the overlays for your own MAF / CNA calls.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The base matrix, the overlays and the <code>config</code> <strong>are</strong> the figure — one portable JSON spec that renders the same from R, Python, or a web page.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../clustered-heatmap-in-javascript/">A clustered heatmap in JavaScript</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Source &amp; npm: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>JavaScript</category>
  <category>CanvasXpress</category>
  <category>oncoprint</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/js/oncoprint-in-javascript/</guid>
  <pubDate>Wed, 28 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/js/oncoprint-in-javascript/thumbnail.png" medium="image" type="image/png" height="73" width="144"/>
</item>
<item>
  <title>Oncoprints (mutation landscapes) in Python with canvasxpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/python/oncoprint-in-python/</link>
  <description><![CDATA[ 




<p>An oncoprint is the standard way to show a <strong>mutation landscape</strong>: genes down one axis, tumours along the other, each cell stacking the alterations that gene carries in that sample — copy-number amplification/deletion plus mutation type — with frequencies alongside. In Python there is no first-class oncoprint; people hand-build one in matplotlib. Here we build an interactive one with <a href="https://pypi.org/project/canvasxpress/">canvasxpress</a>, from a single portable spec.</p>
<section id="install" class="level2">
<h2 class="anchored" data-anchor-id="install">Install</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install canvasxpress</span></code></pre></div>
</section>
<section id="the-data-shape" class="level2">
<h2 class="anchored" data-anchor-id="the-data-shape">The data shape</h2>
<p>An oncoprint is a <code>Heatmap</code> with <strong>overlay matrices</strong>: a base matrix (<code>y</code>, here expression) plus same-shaped layers for copy-number (<code>data2</code>) and mutation (<code>data3</code>). Each overlay cell is a string like <code>"Amplification"</code>, <code>"Missense"</code>, or <code>""</code> for none.</p>
<div id="4be930d8" class="cell" data-execution_count="1">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> random</span>
<span id="cb2-2">random.seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb2-3"></span>
<span id="cb2-4">genes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TP53"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"KRAS"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PIK3CA"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PTEN"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"EGFR"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BRAF"</span>,</span>
<span id="cb2-5">         <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"APC"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RB1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NF1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MYC"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CDKN2A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ARID1A"</span>]</span>
<span id="cb2-6">samples <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"T</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:02d}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span>)]</span>
<span id="cb2-7">mutrate <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {g: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">max</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(genes))) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i, g <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">enumerate</span>(genes)}</span>
<span id="cb2-8"></span>
<span id="cb2-9">CNA <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Amplification"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Deletion"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> MUT <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Missense"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Nonsense"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Truncating"</span>]</span>
<span id="cb2-10">base, cna, mut <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [], [], []</span>
<span id="cb2-11"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> g <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> genes:</span>
<span id="cb2-12">    base.append([<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(random.gauss(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> samples])</span>
<span id="cb2-13">    cna.append([random.choice(CNA) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> random.random() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> mutrate[g] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> samples])</span>
<span id="cb2-14">    mut.append([random.choice(MUT) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> random.random() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> mutrate[g] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">else</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> samples])</span>
<span id="cb2-15"></span>
<span id="cb2-16">subtype <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [random.choice([<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Basal"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Luminal"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"HER2"</span>]) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> samples]</span>
<span id="cb2-17">pathway <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TSG"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Oncogene"</span>)[i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">%</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">len</span>(genes))]</span></code></pre></div>
</div>
</section>
<section id="the-plot" class="level2">
<h2 class="anchored" data-anchor-id="the-plot">The plot</h2>
<p>The overlays go in the <code>y</code> object alongside the base <code>data</code>; <code>oncoprintCNA</code> / <code>oncoprintMUT</code> name them, and <code>xAxis</code> lists the samples.</p>
<div id="34910405" class="cell" data-execution_count="2">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.canvas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CanvasXpress</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.render.jupyter <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CXNoteBook</span>
<span id="cb3-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> IPython.display <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> display</span>
<span id="cb3-4"></span>
<span id="cb3-5">data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"y"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vars"</span>: genes, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"smps"</span>: samples, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: base, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data2"</span>: cna, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data3"</span>: mut},</span>
<span id="cb3-6">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Subtype"</span>: subtype}, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"z"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Pathway"</span>: pathway}}</span>
<span id="cb3-7">config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heatmap"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"oncoprintCNA"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data2"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"oncoprintMUT"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data3"</span>,</span>
<span id="cb3-8">          <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"overlaysThickness"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"xAxis"</span>: samples,</span>
<span id="cb3-9">          <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mutation landscape: 12 genes across 28 tumours"</span>}</span>
<span id="cb3-10"></span>
<span id="cb3-11">cx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CanvasXpress(render_to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"onco"</span>, data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>data, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>config, width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">820</span>, height<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">440</span>)</span>
<span id="cb3-12"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> part <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> CXNoteBook(cx).render():</span>
<span id="cb3-13">    display(part)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="onco" width="820" height="440"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("onco");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart onco removed for re-rendering.");
  } else {
    console.log("Chart onco ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart onco could not be cleaned for re-rendering:", error);
}

var chart_onco = new CanvasXpress({"renderTo": "onco", "data": {"y": {"vars": ["TP53", "KRAS", "PIK3CA", "PTEN", "EGFR", "BRAF", "APC", "RB1", "NF1", "MYC", "CDKN2A", "ARID1A"], "smps": ["T01", "T02", "T03", "T04", "T05", "T06", "T07", "T08", "T09", "T10", "T11", "T12", "T13", "T14", "T15", "T16", "T17", "T18", "T19", "T20", "T21", "T22", "T23", "T24", "T25", "T26", "T27", "T28"], "data": [[-1.18, -1.15, 0.67, -2.29, -0.14, -2.26, 1.1, 0.2, 1.36, -0.5, 0.4, -0.29, -0.74, 0.15, -1.26, -0.35, 0.7, 0.06, -0.41, 2.19, 0.06, -0.59, 0.16, -0.52, -0.39, -0.35, 2.03, 0.02], [-1.0, -0.21, 0.11, 1.34, 0.51, -0.98, -0.3, 0.16, 0.22, -0.13, -1.91, 0.08, 1.11, 1.19, 1.34, -0.44, 0.11, -0.46, -0.52, 0.23, 0.47, -0.69, -3.65, 1.11, 1.64, -2.19, -1.11, 0.33], [-1.04, -1.21, 0.58, 0.1, -1.35, 0.52, 0.29, 1.49, -0.2, -0.21, -0.7, 0.13, 0.5, 0.18, -0.26, 0.58, 0.09, 0.25, -0.96, 0.21, -1.02, -0.86, 0.16, 2.15, 1.02, 0.0, -0.18, 1.01], [-1.31, -1.0, 1.25, 1.14, -0.39, 1.17, -0.43, 0.72, -1.1, -0.21, -1.06, 1.27, -0.23, -0.15, -0.02, 1.1, 1.81, -1.05, -0.16, -0.05, 0.19, -1.04, -1.4, -0.72, -0.77, -0.85, 0.84, -0.52], [-0.73, -0.24, 0.0, -1.21, 0.49, 0.54, -1.13, 1.18, 0.68, 1.43, -0.24, -0.35, -0.22, -0.38, 0.95, 0.95, 0.15, 2.04, -0.88, 0.11, 0.07, -0.23, -0.05, -0.33, 1.44, 2.0, -0.3, -0.65], [-1.63, -1.48, -0.41, -1.46, 0.38, 0.87, 2.9, 1.3, -1.69, 0.34, 0.31, 0.61, 1.32, 0.37, -0.12, -0.79, -1.07, 0.26, -0.26, -0.55, 1.86, 0.39, 0.67, -1.1, 1.47, -0.59, 0.15, 1.8], [0.59, -1.33, 1.55, -0.45, -0.24, -0.75, 0.37, -0.91, 0.25, 0.27, 0.38, 0.68, -0.37, -0.73, 1.57, 0.66, -0.22, -0.08, 0.5, 0.17, -1.24, 1.55, 1.31, -0.43, 0.13, 1.05, -0.58, 0.68], [0.85, 0.15, -0.84, 0.76, -0.29, -0.97, 1.83, -0.2, 1.36, -0.71, -0.6, -1.09, 0.29, -0.91, -1.26, -0.84, -0.81, -0.11, 0.38, 0.2, -0.81, 1.04, 0.1, -1.58, -0.8, 2.16, -0.24, 1.57], [0.78, 0.92, 0.58, 0.29, -0.96, 0.2, 1.73, -1.22, -1.34, -1.18, 0.03, -0.05, -0.23, -0.43, -0.49, 0.82, 0.09, -1.31, -0.82, 0.32, 0.08, -0.63, 0.99, -0.78, -1.77, -0.98, 0.65, -0.69], [-0.21, 0.04, 0.92, 1.45, -1.98, -0.0, 1.37, -0.54, -0.98, -0.9, 0.22, 1.02, -0.31, -1.8, 0.48, -0.95, 0.14, -0.1, 0.24, -0.55, -0.45, 0.72, 0.69, 1.77, 0.85, 0.45, -0.51, 0.4], [0.86, -0.44, -1.55, -0.3, 2.26, -0.94, 0.85, -0.06, 1.16, 2.01, 0.96, 0.51, -0.11, -1.22, -1.74, 1.46, -0.39, 1.21, 0.26, -0.48, -0.69, 0.94, -0.62, -0.27, -0.34, 0.1, 0.78, 0.48], [-0.84, -0.71, 1.87, 2.58, -0.68, -0.83, -1.0, -0.11, 0.73, 2.1, 0.57, 1.03, 0.84, -0.36, 1.06, 0.11, -1.09, -0.46, 0.67, -0.21, 0.04, 0.61, -0.72, -0.25, -0.54, 1.28, 0.35, 0.99]], "data2": [["Amplification", "", "Amplification", "", "", "", "", "Amplification", "", "", "", "", "Amplification", "", "", "", "", "", "", "Deletion", "", "", "", "", "", "Amplification", "", ""], ["", "", "", "", "Deletion", "", "", "Deletion", "", "Deletion", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""], ["Deletion", "", "", "", "", "", "", "", "", "Deletion", "", "", "", "Deletion", "", "", "", "", "", "", "Amplification", "", "", "", "", "", "", ""], ["", "", "", "", "", "Amplification", "", "", "", "", "", "Deletion", "", "", "", "", "", "", "Amplification", "", "Amplification", "", "Deletion", "", "", "", "Amplification", ""], ["Deletion", "", "Deletion", "", "", "", "", "", "", "Deletion", "", "", "", "", "", "", "", "", "", "Amplification", "", "", "", "", "", "", "", ""], ["Deletion", "Amplification", "", "", "", "Deletion", "", "", "", "", "", "", "", "", "", "", "", "Amplification", "", "", "", "Deletion", "", "", "", "", "", ""], ["Amplification", "", "Amplification", "", "", "", "", "", "", "", "", "", "", "Amplification", "", "", "", "Deletion", "", "", "Amplification", "", "", "", "", "", "", ""], ["Amplification", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Deletion", "", "", "", "", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", "", "", "Deletion", "", "Deletion", "", "", "Deletion", "Deletion", "", "", "", "", "", "", "", "", "", "", ""], ["", "", "Amplification", "", "", "", "", "Deletion", "", "", "Deletion", "", "", "", "", "", "", "Amplification", "", "", "", "", "", "", "", "", "", ""], ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Amplification", "", "", "", "", "Deletion", ""], ["", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""]], "data3": [["Truncating", "", "Truncating", "", "Truncating", "Missense", "Missense", "", "", "Nonsense", "", "Nonsense", "Truncating", "", "Nonsense", "Missense", "Truncating", "", "", "Truncating", "", "Nonsense", "Missense", "", "", "Nonsense", "Missense", "Truncating"], ["", "Truncating", "", "Nonsense", "", "", "", "", "Truncating", "Nonsense", "Missense", "", "", "", "", "", "", "Nonsense", "", "", "", "", "", "Truncating", "", "", "Truncating", ""], ["", "", "", "", "Missense", "", "Nonsense", "", "Nonsense", "", "Nonsense", "Missense", "Truncating", "", "Missense", "", "", "Truncating", "", "Nonsense", "", "Nonsense", "", "", "Nonsense", "", "", ""], ["", "", "", "Nonsense", "", "", "Missense", "", "Truncating", "Truncating", "Nonsense", "", "Truncating", "", "", "", "Nonsense", "Truncating", "", "", "", "Missense", "Nonsense", "Truncating", "", "Truncating", "", "Missense"], ["", "", "Nonsense", "Missense", "", "Nonsense", "", "", "", "Missense", "", "", "Missense", "", "", "Missense", "", "", "", "", "Truncating", "Nonsense", "", "", "Missense", "", "", ""], ["", "", "", "Missense", "Nonsense", "Nonsense", "", "", "Missense", "", "", "", "", "", "Nonsense", "", "Missense", "", "", "", "Nonsense", "", "", "Nonsense", "", "", "", ""], ["", "", "Nonsense", "", "", "", "", "Nonsense", "", "Missense", "", "Missense", "", "", "", "", "", "", "", "", "", "Missense", "", "Truncating", "", "", "", "Truncating"], ["Nonsense", "", "", "", "", "Truncating", "", "Truncating", "Truncating", "", "", "", "", "", "", "", "", "", "Nonsense", "Missense", "Nonsense", "", "", "Missense", "", "Truncating", "", "Nonsense"], ["", "Nonsense", "Nonsense", "", "", "", "Missense", "", "", "", "", "", "", "", "Missense", "Missense", "", "Nonsense", "", "", "", "Missense", "", "", "Truncating", "Nonsense", "", ""], ["", "Nonsense", "", "", "", "", "", "", "", "", "", "", "", "", "", "Missense", "", "", "", "", "Truncating", "", "", "", "", "", "", "Missense"], ["", "", "", "", "", "", "Truncating", "", "Truncating", "", "", "", "", "Truncating", "", "", "", "", "", "", "", "", "", "", "", "", "", ""], ["Missense", "", "", "", "", "", "", "Truncating", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "Truncating", ""]]}, "x": {"Subtype": ["Basal", "Luminal", "HER2", "HER2", "Basal", "Basal", "Luminal", "HER2", "HER2", "Basal", "Basal", "Luminal", "Basal", "HER2", "Luminal", "Luminal", "Luminal", "HER2", "HER2", "HER2", "HER2", "Luminal", "Luminal", "Basal", "HER2", "HER2", "Luminal", "Luminal"]}, "z": {"Pathway": ["TSG", "Oncogene", "TSG", "Oncogene", "TSG", "Oncogene", "TSG", "Oncogene", "TSG", "Oncogene", "TSG", "Oncogene"]}}, "config": {"graphType": "Heatmap", "oncoprintCNA": "data2", "oncoprintMUT": "data3", "overlaysThickness": 100, "xAxis": ["T01", "T02", "T03", "T04", "T05", "T06", "T07", "T08", "T09", "T10", "T11", "T12", "T13", "T14", "T15", "T16", "T17", "T18", "T19", "T20", "T21", "T22", "T23", "T24", "T25", "T26", "T27", "T28"], "title": "Mutation landscape: 12 genes across 28 tumours"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
<p>canvasXpress sorts the waterfall for you and shows the alteration frequency per row. Hover a cell to read the exact alteration; swap the overlays for your own MAF / CNA calls.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The base matrix, the overlays and the <code>config</code> <strong>are</strong> the figure — one portable JSON spec that renders the identical oncoprint from R or JavaScript, and can be validated and re-rendered later.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../clustered-heatmap-in-python/">A clustered heatmap in Python</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Package: <a href="https://pypi.org/project/canvasxpress/" class="uri">https://pypi.org/project/canvasxpress/</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>canvasxpress</category>
  <category>oncoprint</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/python/oncoprint-in-python/</guid>
  <pubDate>Tue, 27 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/python/oncoprint-in-python/thumbnail.png" medium="image" type="image/png" height="73" width="144"/>
</item>
<item>
  <title>Oncoprints (mutation landscapes) in R with canvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/r/oncoprint-in-r/</link>
  <description><![CDATA[ 




<p>An oncoprint is the standard way to show a <strong>mutation landscape</strong>: genes down one axis, tumours along the other, each cell stacking the alterations that gene carries in that sample — copy-number amplification/deletion plus mutation type — with per-gene (or per-sample) frequencies alongside. In R the usual tool is <code>ComplexHeatmap::oncoPrint</code>. Here we build an interactive one with <a href="https://canvasxpress.org">canvasXpress</a>, from a single portable spec.</p>
<section id="the-data-shape" class="level2">
<h2 class="anchored" data-anchor-id="the-data-shape">The data shape</h2>
<p>An oncoprint is a <code>Heatmap</code> with <strong>overlay matrices</strong>: a base matrix (<code>y</code>, here expression) plus same-shaped layers for copy-number (<code>data2</code>) and mutation (<code>data3</code>). Each overlay cell is a string like <code>"Amplification"</code>, <code>"Missense"</code>, or <code>""</code> for none.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(canvasXpress)</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">5</span>)</span>
<span id="cb1-4">genes   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TP53"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"KRAS"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PIK3CA"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"PTEN"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"EGFR"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"BRAF"</span>,</span>
<span id="cb1-5">             <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"APC"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"RB1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"NF1"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"MYC"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CDKN2A"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"ARID1A"</span>)</span>
<span id="cb1-6">samples <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"T%02d"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">28</span>)</span>
<span id="cb1-7">mutrate <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">setNames</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pmax</span>(<span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.05</span>, <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> (<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span> <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq_along</span>(genes) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(genes))), genes)</span>
<span id="cb1-8"></span>
<span id="cb1-9">base <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(genes) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(samples)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb1-10">               <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(genes), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dimnames =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(genes, samples))</span>
<span id="cb1-11"></span>
<span id="cb1-12">CNA <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Amplification"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Deletion"</span>); MUT <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Missense"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Nonsense"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Truncating"</span>)</span>
<span id="cb1-13">cna <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> mut <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(genes), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(samples), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dimnames =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(genes, samples))</span>
<span id="cb1-14"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (g <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> genes) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (s <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> samples) {</span>
<span id="cb1-15">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> mutrate[g])       mut[g, s] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(MUT, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb1-16">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">runif</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> mutrate[g] <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fl" style="color: #AD0000;
background-color: null;
font-style: inherit;">0.5</span>) cna[g, s] <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(CNA, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)</span>
<span id="cb1-17">}</span>
<span id="cb1-18"></span>
<span id="cb1-19">smpAnnot <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Subtype =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Basal"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Luminal"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"HER2"</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(samples), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">replace =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>),</span>
<span id="cb1-20">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> samples)</span>
<span id="cb1-21">varAnnot <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Pathway =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"TSG"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Oncogene"</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(genes)),</span>
<span id="cb1-22">                      <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> genes)</span></code></pre></div>
</div>
</section>
<section id="the-plot" class="level2">
<h2 class="anchored" data-anchor-id="the-plot">The plot</h2>
<p>Pass the overlays in a named <code>data</code> list and point <code>oncoprintCNA</code> / <code>oncoprintMUT</code> at them. <code>xAxis</code> lists the samples.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">canvasXpress</span>(</span>
<span id="cb2-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data          =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">y =</span> base, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data2 =</span> cna, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data3 =</span> mut),</span>
<span id="cb2-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">smpAnnot      =</span> smpAnnot, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">varAnnot =</span> varAnnot,</span>
<span id="cb2-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType     =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Heatmap"</span>,</span>
<span id="cb2-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">oncoprintCNA  =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data2"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">oncoprintMUT =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data3"</span>,</span>
<span id="cb2-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">overlaysThickness =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>,</span>
<span id="cb2-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">xAxis         =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.list</span>(samples),</span>
<span id="cb2-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title         =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Mutation landscape: 12 genes across 28 tumours"</span>,</span>
<span id="cb2-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width         =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">820</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">440</span></span>
<span id="cb2-10">)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-f507e1075fa7679317df" style="width:100%;height:348px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-f507e1075fa7679317df">{"x":{"data":{"y":{"data2":[["","","","","","Amplification","","","","","","","","Amplification","Deletion","","Amplification","","","","","","","Amplification","","","",""],["","Amplification","","","","Deletion","","","","","Deletion","","","","","Amplification","Amplification","","Deletion","Deletion","","Amplification","","","","","","Deletion"],["","Deletion","Deletion","","","Amplification","","Deletion","Amplification","Deletion","","","","","","","Amplification","","Deletion","","","","","","","","",""],["","Deletion","","Deletion","","","","Deletion","","","","","","","","","Deletion","","","","","","","","","","",""],["Amplification","","Deletion","","","","Amplification","","","","","","Amplification","Amplification","","","","","","","","","","","","","",""],["","","","","","","","","","","","","","","","","","Deletion","","","Amplification","","","","","","",""],["","","","","","Deletion","","","","","","","","","","","","","","","Deletion","","","","","","",""],["","","","","","","","","","","","","","","","","","","","","Deletion","","","","","","",""],["","","","","Amplification","","","Amplification","","","","","","","","Amplification","","","","","","","","","","","",""],["","","","","","","","","","","","","Deletion","","Deletion","","","","","","","","","","","","",""],["","","","","","","","","","","","","","","","","","","","Deletion","","","","","","","",""],["","","","","","","","","","","","","","","","","","","","","","","","","","","",""]],"data3":[["Missense","","Missense","Missense","Truncating","","Nonsense","Missense","","","Missense","Missense","","Nonsense","Nonsense","","Missense","Truncating","","Missense","","Truncating","","","","Nonsense","Missense","Truncating"],["","","","Nonsense","","Truncating","Nonsense","Truncating","","","Nonsense","","Missense","Missense","","Missense","","Missense","","","","Nonsense","","","","Missense","",""],["","","","","","","","Missense","","","Nonsense","","","","","","Missense","","","","","","","","Nonsense","Nonsense","","Missense"],["Nonsense","","","Truncating","","Truncating","","Truncating","Nonsense","","","Truncating","","","Nonsense","","","","Missense","","Nonsense","Missense","Missense","","Truncating","Truncating","Truncating",""],["","","","","","","Nonsense","","","","Missense","","","","Missense","","","Nonsense","Truncating","Truncating","","","Nonsense","","","Missense","",""],["","Missense","Truncating","","","","","Missense","","","","","Nonsense","","","Missense","Truncating","","","Truncating","Missense","","","Truncating","","","",""],["","Truncating","","","","","Missense","","Missense","Nonsense","","","Truncating","","","","","","","","","","","","","Nonsense","",""],["","","","","Truncating","","","","","","Missense","","Missense","","","","","","","","Missense","Nonsense","","","Missense","","Missense",""],["","","","","","","","","Nonsense","","","","","","","","","","","Nonsense","","","Missense","","","","","Missense"],["","","","","","","Truncating","","","","","","Missense","","","","","","","","","Missense","","","Missense","Nonsense","",""],["","","","","","","","","","","","","Truncating","Truncating","","","","","","","","","","","","","",""],["","","","","","","","","","","","Missense","","","","","","","","","","","Missense","","","","",""]],"smps":["T01","T02","T03","T04","T05","T06","T07","T08","T09","T10","T11","T12","T13","T14","T15","T16","T17","T18","T19","T20","T21","T22","T23","T24","T25","T26","T27","T28"],"vars":["TP53","KRAS","PIK3CA","PTEN","EGFR","BRAF","APC","RB1","NF1","MYC","CDKN2A","ARID1A"],"data":[[-0.84,-1.08,0.82,-1.01,-0.72,-1.14,0.35,0.68,-0.35,-0.75,1.17,-1.24,-0.31,-0.34,-0.02,2.18,-0.51,0.28,-0.14,-0.88,0.3,0.16,0.07,-1.34,1.85,1.21,0.77,-0.94],[1.38,-0.16,-0.29,-2,-0.07,0.85,0.03,-0.71,-0.54,1.28,0.88,-0.1,-0.42,1.2,-0.49,-0.68,0.45,0.41,1.42,-3.5,-0.12,-0.39,2.2,0.15,-0.69,0.19,-1.09,-1.11],[-1.26,-1.07,1.42,-1.76,1.46,-0.58,0.41,2.39,-0.18,-0.95,-1.32,0.73,0.1,-0.44,-1.44,0.75,-0.19,0.61,0.49,-0.38,-0.06,-1.84,0.8,0.29,-0.22,1.96,0.07,0.63],[0.07,-0.14,1.5,-0.14,0.19,0.5,-0.16,-0.47,-0.06,1.62,-1.64,0.46,-0.23,0.19,0.14,0.97,1.34,0.94,0.6,0.98,1.47,-1.54,-0.54,-0.12,0.68,0.14,1.61,-0.23],[1.71,-0.6,-0.66,1.55,1.02,-0.76,0.97,-0.08,-2,2.6,1.06,0.29,-1.42,-2.62,-1.23,-1.26,0.82,-0.37,0.21,-0.56,-1.48,-0.59,-1.6,0.13,0.52,-1.58,1.23,-1.37],[-0.6,-2.18,-0.85,-0.8,-0.59,-0.34,0.12,-0.52,1.14,0.14,0.29,-1.07,-0.39,2.25,-1.75,-0.28,0.08,0.74,-0.03,-0.63,-0.68,-0.85,-0.73,-0.77,0.08,-0.8,-0.38,-0.75],[-0.47,0.24,0.32,-0.07,-0.11,-2.1,0.19,0.93,0.68,-1.35,-0.4,0.65,0.95,0.09,-0.04,-0.19,-0.65,1.22,2.03,-0.53,0.46,0.78,-0.36,-1.01,0.05,1.22,-1.35,-1.13],[-0.64,-0.26,1.11,1.9,-0.92,-0.3,-0.56,-1.06,0.21,0.8,1.24,0.3,0.75,1.63,0.33,-0.38,0.73,0.63,-0.37,1.9,-0.18,-0.03,-0.99,0.97,-0.74,-0.37,0.36,-0.22],[-0.29,0.9,2.22,-0.46,0.75,-1.27,0.5,0.56,-0.06,-1.55,-1.37,-0.8,-0.52,-0.51,1.57,0.74,-0.11,0.53,-1.58,1.4,-1.16,-1.46,-0.73,-0.42,0.97,-0.16,-0.36,-0.13],[0.14,0.94,1.22,0.56,-0.11,-0.28,-1.74,0.9,0.89,0.46,-1.44,-0.03,0.81,-0.66,-1.07,-1.17,-0.3,-0.47,-0.12,-0.75,0.41,0.09,1.47,-0.83,0.98,0.56,1.37,-0.82],[1.23,1.47,1.48,-0.89,-0.06,-0.2,0.98,0.99,-0.23,0.05,1.35,2.18,-0.61,-0.04,0.92,0.67,0.99,0.82,-1.8,-0.31,-0.26,0.98,1.86,1.4,0.19,-0.86,0.29,0.47],[-0.8,0.71,0.95,-0.46,0.23,-0.23,-0.02,0.38,-1.97,-0.2,-1.98,0.96,1.24,-0.12,-0.59,0.37,-0.78,-0.43,-0.48,1.17,-0.27,-0.6,0,0.02,0.27,1.24,0.71,-0.87]]},"x":{"Subtype":["Luminal","Basal","Luminal","HER2","Basal","HER2","Basal","Basal","HER2","Basal","Luminal","Basal","Luminal","Basal","Basal","Basal","HER2","HER2","Basal","Basal","Luminal","HER2","HER2","HER2","Luminal","Luminal","HER2","Basal"]},"z":{"Pathway":["TSG","Oncogene","TSG","Oncogene","TSG","Oncogene","TSG","Oncogene","TSG","Oncogene","TSG","Oncogene"]}},"config":{"graphType":"Heatmap","isR":true,"oncoprintCNA":"data2","oncoprintMUT":"data3","overlaysThickness":100,"xAxis":["T01","T02","T03","T04","T05","T06","T07","T08","T09","T10","T11","T12","T13","T14","T15","T16","T17","T18","T19","T20","T21","T22","T23","T24","T25","T26","T27","T28"],"title":"Mutation landscape: 12 genes across 28 tumours"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>canvasXpress sorts the waterfall for you and shows the alteration frequency per row. Hover a cell to read the exact alteration; swap the overlays for your own MAF / CNA calls.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The base matrix, the overlays and the <code>config</code> <strong>are</strong> the figure — one portable spec. The same spec renders the identical oncoprint from Python or JavaScript, and can be validated and re-rendered later.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../clustered-heatmap-in-r/">A clustered heatmap in R</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Package: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>R</category>
  <category>canvasXpress</category>
  <category>oncoprint</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/r/oncoprint-in-r/</guid>
  <pubDate>Mon, 26 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/r/oncoprint-in-r/thumbnail.png" medium="image" type="image/png" height="73" width="144"/>
</item>
<item>
  <title>Circular (Circos-style) multi-track plots in JavaScript with CanvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/js/circos-plots-in-javascript/</link>
  <description><![CDATA[ 




<p>A circular (Circos-style) plot wraps a genome — or any ordered set of segments — into a ring, stacks several <strong>data tracks</strong> around it, and draws <strong>ribbons</strong> for relationships between positions. Building one in the browser by hand is serious trigonometry. CanvasXpress is a JavaScript library at heart, so it’s a <code>tracks × segments</code> matrix plus a <code>config</code>.</p>
<section id="load-the-library" class="level2">
<h2 class="anchored" data-anchor-id="load-the-library">Load the library</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb1-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">link</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> href</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> rel</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"stylesheet"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> src</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="the-markup-and-the-spec" class="level2">
<h2 class="anchored" data-anchor-id="the-markup-and-the-spec">The markup and the spec</h2>
<p>Rows are the tracks you draw, columns are the positions around the ring; <code>Region</code> segments the ring, and <code>circularConnections</code> is a list of <code>[colour, from, to]</code> ribbons.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb2-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"circ"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"560"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"560"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> segments <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> tracks <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expression"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Methylation"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CopyNumber"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Density"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-4">      cols <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(220,40,40)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(40,120,220)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(40,160,60)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(240,150,20)"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-5">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>) segments<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"s"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-6">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pick</span>(a) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> a[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">floor</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> a<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length</span>)]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> }</span>
<span id="cb2-7"></span>
<span id="cb2-8">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> data_m <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> tracks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> () {</span>
<span id="cb2-9">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> segments<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> () { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>((<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">-</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">100</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-10">  })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-11">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> region <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> segments<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (_<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> i) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"chr"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">floor</span>(i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">/</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>) <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-12">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> conns <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-13">  <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> (<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> c <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> c <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&lt;</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> c<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">++</span>) conns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>([<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pick</span>(cols)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pick</span>(segments)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">pick</span>(segments)])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-14"></span>
<span id="cb2-15">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">y</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">vars</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> tracks<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">smps</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> segments<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> data_m }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">x</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Region</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> region } }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-16">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb2-17">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Circular"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-18">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">circularConnections</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> conns<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-19">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">circularTrackGraphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bar"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"heatmap"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"line"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dot"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-20">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">circularTrackGraphWeight</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-21">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">circularTrackName</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-22">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">segregateSamplesBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Region"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-23">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Circos-style multi-track plot with connections"</span></span>
<span id="cb2-24">  }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-25"></span>
<span id="cb2-26">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CanvasXpress</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"circ"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> config)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-27"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="live-result" class="level2">
<h2 class="anchored" data-anchor-id="live-result">Live result</h2>
<link href="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@73.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"></script>
<canvas id="circLive" width="560" height="560"></canvas>
<script>
(function () {
  function draw() {
    if (typeof CanvasXpress === "undefined") { return setTimeout(draw, 60); }
    var segments = [], tracks = ["Expression", "Methylation", "CopyNumber", "Density"],
        cols = ["rgb(220,40,40)", "rgb(40,120,220)", "rgb(40,160,60)", "rgb(240,150,20)"];
    for (var i = 0; i < 80; i++) segments.push("s" + (i + 1));
    function pick(a) { return a[Math.floor(Math.random() * a.length)]; }
    var data_m = tracks.map(function () {
      return segments.map(function () { return Math.round((Math.random() * 4 - 2) * 100) / 100; });
    });
    var region = segments.map(function (_, i) { return "chr" + (Math.floor(i / 20) + 1); });
    var conns = [];
    for (var c = 0; c < 18; c++) conns.push([pick(cols), pick(segments), pick(segments)]);
    new CanvasXpress("circLive",
      { y: { vars: tracks, smps: segments, data: data_m }, x: { Region: region } },
      { graphType: "Circular", circularConnections: conns,
        circularTrackGraphType: ["bar", "heatmap", "line", "dot"],
        circularTrackGraphWeight: [30, 20, 25, 25], circularTrackName: [1, 2, 3, 4],
        segregateSamplesBy: ["Region"], title: "Circos-style multi-track plot with connections" });
  }
  draw();
})();
</script>
<p>Each ring is one track; the inner ribbons are the connections. Hover a segment to read its values; swap the matrix and ribbons for your own genomic tracks and interactions.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The matrix, the connections and the <code>config</code> <strong>are</strong> the figure — one portable JSON spec that renders the same from R, Python, or a web page.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../genome-tracks-in-javascript/">Genome browser tracks in JavaScript</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Source &amp; npm: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>JavaScript</category>
  <category>CanvasXpress</category>
  <category>circos</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/js/circos-plots-in-javascript/</guid>
  <pubDate>Sun, 25 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/js/circos-plots-in-javascript/thumbnail.png" medium="image" type="image/png" height="139" width="144"/>
</item>
<item>
  <title>Circular (Circos-style) multi-track plots in Python with canvasxpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/python/circos-plots-in-python/</link>
  <description><![CDATA[ 




<p>A circular (Circos-style) plot wraps a genome — or any ordered set of segments — into a ring, stacks several <strong>data tracks</strong> around it, and draws <strong>ribbons</strong> for relationships between positions. In Python the usual tool is <code>pyCirclize</code>. Here we build an interactive one with <a href="https://pypi.org/project/canvasxpress/">canvasxpress</a>, from a single portable spec.</p>
<section id="install" class="level2">
<h2 class="anchored" data-anchor-id="install">Install</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install canvasxpress</span></code></pre></div>
</section>
<section id="the-data-shape" class="level2">
<h2 class="anchored" data-anchor-id="the-data-shape">The data shape</h2>
<p>The matrix is <strong>tracks × segments</strong> (rows are the tracks you draw, columns are the positions around the ring). A sample annotation segments the ring (here into chromosomes), and <code>circularConnections</code> is a list of <code>[colour, from, to]</code> ribbons.</p>
<div id="08da4624" class="cell" data-execution_count="1">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> random</span>
<span id="cb2-2">random.seed(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span>
<span id="cb2-3"></span>
<span id="cb2-4">segments <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"s</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span>)]</span>
<span id="cb2-5">tracks   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expression"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Methylation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CopyNumber"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Density"</span>]</span>
<span id="cb2-6">data_m   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [[<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">round</span>(random.gauss(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>) <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> segments] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> tracks]</span>
<span id="cb2-7"></span>
<span id="cb2-8">region <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">f"chr</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">{</span>i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">//</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">}</span><span class="ss" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span> <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> i <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span>)]</span>
<span id="cb2-9">cols   <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(220,40,40)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(40,120,220)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(40,160,60)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(240,150,20)"</span>]</span>
<span id="cb2-10">conns  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [[random.choice(cols), random.choice(segments), random.choice(segments)] <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> _ <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">range</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>)]</span></code></pre></div>
</div>
</section>
<section id="the-plot" class="level2">
<h2 class="anchored" data-anchor-id="the-plot">The plot</h2>
<p><code>circularTrackGraphType</code> picks a renderer per track (<code>bar</code>, <code>heatmap</code>, <code>line</code>, <code>dot</code>), <code>circularTrackGraphWeight</code> sets each track’s radial thickness, and <code>segregateSamplesBy</code> splits the ring by the annotation.</p>
<div id="d4acc2a2" class="cell" data-execution_count="2">
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.canvas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CanvasXpress</span>
<span id="cb3-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.render.jupyter <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CXNoteBook</span>
<span id="cb3-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> IPython.display <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> display</span>
<span id="cb3-4"></span>
<span id="cb3-5">data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"y"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vars"</span>: tracks, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"smps"</span>: segments, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: data_m}, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>: {<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Region"</span>: region}}</span>
<span id="cb3-6">config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb3-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Circular"</span>,</span>
<span id="cb3-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"circularConnections"</span>: conns,</span>
<span id="cb3-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"circularTrackGraphType"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bar"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"heatmap"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"line"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dot"</span>],</span>
<span id="cb3-10">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"circularTrackGraphWeight"</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>],</span>
<span id="cb3-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"circularTrackName"</span>: [<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>],</span>
<span id="cb3-12">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"segregateSamplesBy"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Region"</span>],</span>
<span id="cb3-13">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Circos-style multi-track plot with connections"</span>,</span>
<span id="cb3-14">}</span>
<span id="cb3-15"></span>
<span id="cb3-16">cx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CanvasXpress(render_to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"circ"</span>, data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>data, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>config, width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">560</span>, height<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">560</span>)</span>
<span id="cb3-17"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> part <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> CXNoteBook(cx).render():</span>
<span id="cb3-18">    display(part)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="circ" width="560" height="560"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("circ");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart circ removed for re-rendering.");
  } else {
    console.log("Chart circ ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart circ could not be cleaned for re-rendering:", error);
}

var chart_circ = new CanvasXpress({"renderTo": "circ", "data": {"y": {"vars": ["Expression", "Methylation", "CopyNumber", "Density"], "smps": ["s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", "s32", "s33", "s34", "s35", "s36", "s37", "s38", "s39", "s40", "s41", "s42", "s43", "s44", "s45", "s46", "s47", "s48", "s49", "s50", "s51", "s52", "s53", "s54", "s55", "s56", "s57", "s58", "s59", "s60", "s61", "s62", "s63", "s64", "s65", "s66", "s67", "s68", "s69", "s70", "s71", "s72", "s73", "s74", "s75", "s76", "s77", "s78", "s79", "s80"], "data": [[0.37, 2.53, 1.1, 1.11, 0.65, 0.38, 0.69, -0.0, -0.7, -0.86, -1.12, 0.34, 0.67, 1.76, 0.62, 0.39, 0.78, 0.1, -1.8, 1.18, -0.36, 0.34, -0.16, 3.09, 1.28, 0.54, -1.05, 1.03, -0.81, 1.3, -1.45, 0.02, 1.07, -0.77, 0.23, 0.28, 1.09, -0.39, 0.83, 2.27, -1.42, -0.77, 0.6, -0.56, -1.27, 1.61, 1.12, 1.28, 1.25, 0.88, -0.72, -2.34, 0.66, -0.99, 0.18, 0.54, -1.17, -0.21, 1.95, 0.94, -1.55, -0.07, 0.14, 0.73, 0.91, 0.07, -0.11, 1.04, -1.36, 1.32, 0.48, -0.39, -0.48, 0.37, -1.41, -2.32, 0.51, 1.63, -0.05, 0.16], [0.08, -0.91, 0.51, 0.94, 0.12, 1.02, -0.98, 0.35, -0.7, -0.44, 0.35, 0.24, 0.95, 0.75, -1.16, 1.4, -1.57, -0.05, 0.36, -0.05, 0.55, 0.06, -0.99, 0.86, -0.04, -0.93, 0.07, -0.02, 0.35, -0.59, 0.18, -0.18, 1.65, -0.37, 1.31, -0.08, 1.16, 2.38, -0.39, 0.15, -0.92, -0.72, -0.57, 0.1, 0.95, 0.91, -0.5, 0.15, -1.49, 0.6, -0.24, -1.1, -0.74, 0.59, 0.1, 0.66, -0.45, 0.16, -0.24, -1.55, -0.16, -0.14, -0.7, 0.8, 2.18, 1.45, 0.04, -1.18, -0.19, -0.64, 0.16, 1.21, -0.05, -1.44, 1.38, 0.06, 1.39, -0.89, 2.54, -1.24], [0.14, 0.83, -2.62, -0.8, -1.62, 1.74, 0.71, -0.97, -1.77, -1.78, 0.17, -0.82, 0.37, -0.54, -1.73, 1.84, 0.5, -0.71, -0.35, 1.33, 0.83, -1.27, 1.49, -0.63, 0.59, -1.23, -0.68, 0.8, -1.22, 0.08, 0.42, -0.67, 1.48, 0.68, -0.14, 1.03, 1.39, 1.26, -0.12, 0.82, 0.4, -1.12, -0.36, 2.06, -0.81, 0.5, 1.73, -0.38, -0.01, -0.76, 0.52, -1.24, 0.46, -0.84, 0.34, -1.74, -1.11, 0.94, 0.6, -3.1, 1.54, -0.84, 0.9, 1.04, -0.17, -0.39, -1.96, 0.47, 1.89, -1.28, 1.14, 0.75, 0.96, -1.09, -0.12, 0.25, 1.73, -0.96, -0.54, -0.79], [0.87, -1.62, -0.21, -1.34, -0.35, 0.76, -0.56, 0.69, -0.49, -0.06, -0.17, -0.91, 0.41, 0.65, -0.82, 0.68, 0.09, -0.45, 0.14, 0.82, 0.74, 1.49, 0.25, 0.2, -1.53, -0.56, 0.58, -1.14, -0.96, 1.83, -0.1, -1.14, -2.16, -0.9, 2.31, -0.04, 0.6, 0.66, -0.51, 0.33, 0.03, -0.35, 1.01, -0.86, -0.78, -0.68, 1.21, -0.51, 1.8, -1.37, -1.02, -2.68, -0.95, 0.06, 0.68, -1.02, -0.55, 1.41, -0.52, 0.08, 0.62, -1.0, 1.22, -0.22, 0.76, -0.32, 0.25, 1.2, 0.2, -1.86, -0.31, -0.41, -0.21, 0.16, -1.66, 1.74, -0.89, 1.27, -0.4, -0.38]]}, "x": {"Region": ["chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr2", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr3", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4", "chr4"]}, "z": null}, "config": {"graphType": "Circular", "circularConnections": [["rgb(220,40,40)", "s11", "s24"], ["rgb(240,150,20)", "s75", "s17"], ["rgb(240,150,20)", "s73", "s75"], ["rgb(220,40,40)", "s48", "s65"], ["rgb(220,40,40)", "s77", "s48"], ["rgb(40,160,60)", "s14", "s41"], ["rgb(220,40,40)", "s62", "s22"], ["rgb(40,120,220)", "s62", "s47"], ["rgb(40,160,60)", "s48", "s55"], ["rgb(40,160,60)", "s5", "s19"], ["rgb(40,160,60)", "s8", "s5"], ["rgb(40,120,220)", "s66", "s47"], ["rgb(240,150,20)", "s47", "s61"], ["rgb(40,120,220)", "s39", "s18"], ["rgb(40,160,60)", "s3", "s57"], ["rgb(40,160,60)", "s75", "s34"], ["rgb(240,150,20)", "s38", "s38"], ["rgb(240,150,20)", "s64", "s58"]], "circularTrackGraphType": ["bar", "heatmap", "line", "dot"], "circularTrackGraphWeight": [0.3, 0.2, 0.25, 0.25], "circularTrackName": [1, 2, 3, 4], "segregateSamplesBy": ["Region"], "title": "Circos-style multi-track plot with connections"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
<p>Each ring is one track; the inner ribbons are the connections. Hover a segment to read its values; swap the matrix and ribbons for your own genomic tracks and interactions.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The matrix, the connections and the <code>config</code> <strong>are</strong> the figure — one portable JSON spec that renders the identical circular plot from R or JavaScript, and can be validated and re-rendered later.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../genome-tracks-in-python/">Genome browser tracks in Python</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Package: <a href="https://pypi.org/project/canvasxpress/" class="uri">https://pypi.org/project/canvasxpress/</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>canvasxpress</category>
  <category>circos</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/python/circos-plots-in-python/</guid>
  <pubDate>Sat, 24 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/python/circos-plots-in-python/thumbnail.png" medium="image" type="image/png" height="139" width="144"/>
</item>
<item>
  <title>Circular (Circos-style) multi-track plots in R with canvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/r/circos-plots-in-r/</link>
  <description><![CDATA[ 




<p>A circular (Circos-style) plot wraps a genome — or any ordered set of segments — into a ring, stacks several <strong>data tracks</strong> around it, and draws <strong>ribbons</strong> for relationships between positions. In R the reference is <code>circlize</code>. Here we build an interactive one with <a href="https://canvasxpress.org">canvasXpress</a>, from a single portable spec.</p>
<section id="the-data-shape" class="level2">
<h2 class="anchored" data-anchor-id="the-data-shape">The data shape</h2>
<p>The matrix is <strong>tracks × segments</strong> (rows are the tracks you draw, columns are the positions around the ring). A sample annotation segments the ring (here into chromosomes), and <code>circularConnections</code> is a list of <code>[colour, from, to]</code> ribbons.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(canvasXpress)</span>
<span id="cb1-2"></span>
<span id="cb1-3"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">set.seed</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)</span>
<span id="cb1-4">segments <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"s"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">80</span>)</span>
<span id="cb1-5">tracks   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Expression"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Methylation"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CopyNumber"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Density"</span>)</span>
<span id="cb1-6">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">matrix</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">round</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rnorm</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(tracks) <span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(segments)), <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>),</span>
<span id="cb1-7">            <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">nrow =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">length</span>(tracks), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">dimnames =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(tracks, segments))</span>
<span id="cb1-8"></span>
<span id="cb1-9">smpAnnot <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">data.frame</span>(<span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">Region =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rep</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">paste0</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"chr"</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">each =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>), <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> segments)</span>
<span id="cb1-10"></span>
<span id="cb1-11">cols  <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">c</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(220,40,40)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(40,120,220)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(40,160,60)"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"rgb(240,150,20)"</span>)</span>
<span id="cb1-12">conns <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">lapply</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">18</span>, <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span>(i)</span>
<span id="cb1-13">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(cols, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(segments, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>), <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sample</span>(segments, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)))</span></code></pre></div>
</div>
</section>
<section id="the-plot" class="level2">
<h2 class="anchored" data-anchor-id="the-plot">The plot</h2>
<p><code>circularTrackGraphType</code> picks a renderer per track (<code>bar</code>, <code>heatmap</code>, <code>line</code>, <code>dot</code>), <code>circularTrackGraphWeight</code> sets each track’s radial thickness, and <code>segregateSamplesBy</code> splits the ring by the annotation.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb2-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">canvasXpress</span>(</span>
<span id="cb2-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data      =</span> y, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">smpAnnot =</span> smpAnnot,</span>
<span id="cb2-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Circular"</span>,</span>
<span id="cb2-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">circularConnections     =</span> conns,</span>
<span id="cb2-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">circularTrackGraphType  =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bar"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"heatmap"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"line"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"dot"</span>),</span>
<span id="cb2-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">circularTrackGraphWeight =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">30</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">20</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span>),</span>
<span id="cb2-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">circularTrackName        =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">2</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">3</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>),</span>
<span id="cb2-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">segregateSamplesBy       =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Region"</span>),</span>
<span id="cb2-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title     =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Circos-style multi-track plot with connections"</span>,</span>
<span id="cb2-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width     =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">560</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">560</span></span>
<span id="cb2-11">)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-edcd429b618c657e7983" style="width:100%;height:650px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-edcd429b618c657e7983">{"x":{"data":{"y":{"vars":["Expression","Methylation","CopyNumber","Density"],"smps":["s1","s2","s3","s4","s5","s6","s7","s8","s9","s10","s11","s12","s13","s14","s15","s16","s17","s18","s19","s20","s21","s22","s23","s24","s25","s26","s27","s28","s29","s30","s31","s32","s33","s34","s35","s36","s37","s38","s39","s40","s41","s42","s43","s44","s45","s46","s47","s48","s49","s50","s51","s52","s53","s54","s55","s56","s57","s58","s59","s60","s61","s62","s63","s64","s65","s66","s67","s68","s69","s70","s71","s72","s73","s74","s75","s76","s77","s78","s79","s80"],"data":[[-0.08,0.74,-3.01,0.42,1.51,1.28,1.74,0.6,-1.55,0.84,0.36,0.61,0.27,0.59,-0.78,0.56,-0.27,0.4,0.78,-2.9,0.24,-1.68,0.6,-0.5,0.33,0.3,0.03,0.17,0.55,0.26,-1.14,0.48,-1.36,-1.5,0.44,1.34,0.08,-1.03,0.23,0.72,0.32,1.56,-0.38,-0.36,0.77,-1.25,2.19,-0.2,-0.9,0.56,-0.58,-0.02,0.77,0.35,-0.36,-0.87,-0.42,0.17,-0.31,-0.38,-1.04,-0.64,-0.04,-1.34,0.64,-0.35,1.32,-0.53,0.94,-1.66,-2.52,-1.07,0,0.93,0.3,-0.94,-1.47,0.29,0.78,-2.3],[0.84,-0.11,-0.59,-1.29,-0.27,-0.01,-1.11,-2.02,-0.77,-0.7,-0.61,-1.96,-0.64,-0.1,-0.6,0.09,-1.08,-1.6,-0.48,0.58,-0.79,1.22,-3.01,-0.62,-0.04,-1.9,-0.49,0.57,-1.09,1.44,-1.72,0.14,0.84,-1.35,0.5,2.44,-0.7,-0.42,0.26,-0.69,0.58,0.2,0.74,0.99,0.94,-0.38,0.08,-1.04,-0.8,-1.33,-0.22,0.89,-0.98,-0.73,0.16,-1.3,-0.04,1.48,-0.18,-0.61,0.02,0.91,0.28,-0.16,-0.85,0.41,0.42,-1.38,-0.66,-0.24,0.56,0.19,0.51,0.87,-0.5,-1.32,0.3,1.31,-1.08,-0.4],[-0.46,-0.17,-0.76,0.07,1.56,-0.4,-1.06,1.51,1.26,-0.06,0.23,-0.66,1.08,0.97,-1.5,-1.78,-0.49,-1.47,0.09,2.38,-1.09,-0.1,0.77,-1.35,-0.64,-1.65,0.61,-0.16,1.45,-1.19,-0.37,-1.73,2.23,-2.4,1.43,0.68,0.6,0.16,-0.34,0.66,-1.41,-0.39,-1.18,-0.27,-1.05,0.21,2.11,-0.13,1.32,-1.92,1.2,-0.03,0.53,0.71,-1.39,0.89,0.14,-1.55,0.84,-0.85,0.86,-0.58,1.03,-0.25,-0.72,-0.54,-0.74,-0.41,0.46,-0.73,-0.37,-0.7,-0.23,-1.62,0.17,-0.84,0.48,-0.3,0.59,1.13],[-0.55,-1.09,0.29,-0.81,-0.24,0.02,1.95,0.96,0.43,0.47,-0.26,0.28,-0.37,0.58,0.75,-1.11,1.64,1.04,0.6,-0.65,2.04,-0.95,1.57,0.77,-0.07,-1.78,-0.36,-0.84,1.39,-0.3,1.82,0.28,0.17,0.79,-1.83,-1.97,0.8,-0.56,0.3,1.73,-1,0.92,0.28,0.48,1.01,-0.12,1.03,-0.58,1.04,0.02,-1.36,-0.88,0.93,-0.32,1.37,-0.88,0.1,1.37,-0.7,1.45,0.71,0.08,-0.44,0.66,-0.14,-2.23,0.25,1.07,-0.83,0.29,-0.25,-0.05,-0.5,-0.41,-1.48,-0.18,0.07,-0.06,0.33,1.06]]},"x":{"Region":["chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr2","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr3","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4","chr4"]},"z":null},"config":{"graphType":"Circular","isR":true,"circularConnections":[["rgb(40,160,60)","s34","s37"],["rgb(220,40,40)","s75","s72"],["rgb(220,40,40)","s24","s1"],["rgb(220,40,40)","s12","s15"],["rgb(40,160,60)","s22","s44"],["rgb(220,40,40)","s36","s78"],["rgb(220,40,40)","s70","s39"],["rgb(220,40,40)","s65","s78"],["rgb(40,120,220)","s9","s55"],["rgb(240,150,20)","s31","s28"],["rgb(40,120,220)","s22","s64"],["rgb(40,120,220)","s35","s1"],["rgb(40,160,60)","s17","s65"],["rgb(240,150,20)","s11","s23"],["rgb(40,160,60)","s34","s21"],["rgb(220,40,40)","s8","s29"],["rgb(240,150,20)","s65","s64"],["rgb(220,40,40)","s29","s79"]],"circularTrackGraphType":["bar","heatmap","line","dot"],"circularTrackGraphWeight":[30,20,25,25],"circularTrackName":[1,2,3,4],"segregateSamplesBy":["Region"],"title":"Circos-style multi-track plot with connections"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>Each ring is one track; the inner ribbons are the connections. Hover a segment to read its values; swap the matrix and ribbons for your own genomic tracks and interactions.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The matrix, the connections and the <code>config</code> <strong>are</strong> the figure — one portable spec. The same spec renders the identical circular plot from Python or JavaScript, and can be validated and re-rendered later.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../genome-tracks-in-r/">Genome browser tracks in R</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Package: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>R</category>
  <category>canvasXpress</category>
  <category>circos</category>
  <category>bioinformatics</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/r/circos-plots-in-r/</guid>
  <pubDate>Fri, 23 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/r/circos-plots-in-r/thumbnail.png" medium="image" type="image/png" height="139" width="144"/>
</item>
<item>
  <title>Choropleth maps in JavaScript with CanvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/js/choropleth-maps-in-javascript/</link>
  <description><![CDATA[ 




<p>A choropleth shades each region by a value — emissions, incidence, turnout, income. It is the most common map in data analysis and the easiest to get <em>subtly wrong</em>: most “my map is all one colour” complaints are not rendering bugs but scale bugs. CanvasXpress does the join and the colouring inside the render, so in the browser you pass one value per region and a topoJSON of boundaries and get an interactive, reproducible figure — and with the right colour scale it stays vivid on exactly the kind of heavy-tailed data that flattens naive maps.</p>
<section id="first-the-trap-colour-encodes-a-rate-not-a-count" class="level2">
<h2 class="anchored" data-anchor-id="first-the-trap-colour-encodes-a-rate-not-a-count">First, the trap: colour encodes a <em>rate</em>, not a <em>count</em></h2>
<p>A choropleth fills an <strong>area</strong>, and area is a size channel your eye cannot help reading. Shade regions by a raw count — total cases, total emissions, total sales — and big, populous regions light up simply because they are big and populous. You have drawn a population map with extra steps. The fix is almost always to map a <strong>rate or density</strong> (per capita, per 100k); reserve raw counts for a proportional-symbol map, where a sized bubble carries the count honestly.</p>
</section>
<section id="load-the-library" class="level2">
<h2 class="anchored" data-anchor-id="load-the-library">Load the library</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb1-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">link</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> href</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@71.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> rel</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"stylesheet"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> src</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@71.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="the-markup-and-the-spec" class="level2">
<h2 class="anchored" data-anchor-id="the-markup-and-the-spec">The markup and the spec</h2>
<p>The <strong>columns</strong> (<code>smps</code>) are the regions — they match the map by name — and the single <strong>row</strong> (<code>vars</code>) is the variable you colour by: CO₂ emissions per country for 2018. We fetch a prepared table and a small annotation table (continent, ISO code), parse the tab-separated text, and hand the matrix to CanvasXpress. The two choices that make this map <em>work</em> are in the colour scale: a seven-stop viridis <code>colorSpectrum</code>, and <code>colorSpectrumBreaksMethod: "quantile"</code>, which puts an equal number of countries in every colour class — on skewed data that guarantee is what keeps all seven colours on the map.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb2-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"co2quant"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"760"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"520"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> DATA <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/r/cX-CO2-dat.txt"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-4">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> SMP  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/r/cX-CO2-smp.txt"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-5"></span>
<span id="cb2-6">  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// split a tab-separated file into a list of cell-arrays (one per row)</span></span>
<span id="cb2-7">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rows</span>(text) {</span>
<span id="cb2-8">    <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> text<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">trim</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">split</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\n</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (line) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> line<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">split</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-9">  }</span>
<span id="cb2-10"></span>
<span id="cb2-11">  <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Promise</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">all</span>([<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fetch</span>(DATA)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">then</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (r) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">text</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-12">               <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">fetch</span>(SMP )<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">then</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (r) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">text</span>()<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })])</span>
<span id="cb2-13">    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">then</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (texts) {</span>
<span id="cb2-14">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> d <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rows</span>(texts[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span>                      <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// [header, ["CO2", v1, v2, ...]]</span></span>
<span id="cb2-15">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> countries <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> d[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">slice</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span>               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// header, minus the empty corner cell</span></span>
<span id="cb2-16">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> values    <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> d[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">slice</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Number</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span>   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// the CO2 values</span></span>
<span id="cb2-17"></span>
<span id="cb2-18">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> s <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">rows</span>(texts[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>])<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span>                       <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// header + one row per country</span></span>
<span id="cb2-19">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> col <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span>                                 <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// header name -&gt; column index</span></span>
<span id="cb2-20">      s[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">forEach</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (name<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> i) { col[name] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> i<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-21">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> byCountry <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {}<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-22">      s<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">slice</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">forEach</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (r) { byCountry[r[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>]] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> r<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-23">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> continent <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> countries<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (c) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> byCountry[c][col[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Continent"</span>] <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-24"></span>
<span id="cb2-25">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb2-26">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">y</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">vars</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CO2"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">smps</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> countries<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [values] }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-27">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">x</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Continent</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> continent }</span>
<span id="cb2-28">      }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-29">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb2-30">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Map"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-31">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">colorBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CO2"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-32">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">topoJSON</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/maps/WORLD.json"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-33">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">mapId</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"co2Quantile"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-34">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">colorSpectrum</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#440154"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#443983"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#31688e"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#21918c"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-35">                        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#35b779"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#90d743"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#fde725"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-36">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">colorSpectrumBreaksMethod</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"quantile"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-37">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">mapColor</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d9dde3"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-38">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">mapOutlineColor</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#ffffff"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-39">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">legendPosition</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-40">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CO2 emissions per country (2018)"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-41">        <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">subtitle</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Seven quantile classes: each colour holds about 28 of 198 countries"</span></span>
<span id="cb2-42">      }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-43">      <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CanvasXpress</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"co2quant"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> config)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-44">    })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-45"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="live-result" class="level2">
<h2 class="anchored" data-anchor-id="live-result">Live result</h2>
<link href="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@71.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@71.3.0/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"></script>
<canvas id="co2quantLive" width="760" height="520"></canvas>
<script>
(function () {
  var DATA = "https://www.canvasxpress.org/data/r/cX-CO2-dat.txt";
  var SMP  = "https://www.canvasxpress.org/data/r/cX-CO2-smp.txt";
  function rows(text) {
    return text.trim().split("\n").map(function (line) { return line.split("\t"); });
  }
  function draw() {
    if (typeof CanvasXpress === "undefined") { return setTimeout(draw, 60); }
    Promise.all([fetch(DATA).then(function (r) { return r.text(); }),
                 fetch(SMP ).then(function (r) { return r.text(); })])
      .then(function (texts) {
        var d = rows(texts[0]);
        var countries = d[0].slice(1);
        var values    = d[1].slice(1).map(Number);
        var s = rows(texts[1]);
        var col = {};
        s[0].forEach(function (name, i) { col[name] = i; });
        var byCountry = {};
        s.slice(1).forEach(function (r) { byCountry[r[0]] = r; });
        var continent = countries.map(function (c) { return byCountry[c][col["Continent"] + 1]; });
        new CanvasXpress("co2quantLive",
          { y: { vars: ["CO2"], smps: countries, data: [values] }, x: { Continent: continent } },
          { graphType: "Map", colorBy: "CO2",
            topoJSON: "https://www.canvasxpress.org/data/maps/WORLD.json",
            mapId: "co2Quantile",
            colorSpectrum: ["#440154", "#443983", "#31688e", "#21918c",
                            "#35b779", "#90d743", "#fde725"],
            colorSpectrumBreaksMethod: "quantile",
            mapColor: "#d9dde3", mapOutlineColor: "#ffffff", legendPosition: "bottom",
            title: "CO2 emissions per country (2018)",
            subtitle: "Seven quantile classes: each colour holds about 28 of 198 countries" });
      });
  }
  draw();
})();
</script>
<p>Every band of the ramp is doing work: the darkest purples are the smallest emitters, the yellows the largest, and the legend’s break values tell you the class edges are <em>data-driven</em>, not evenly spaced. Hover any country for its name, continent and value.</p>
</section>
<section id="why-not-just-a-plain-linear-ramp" class="level2">
<h2 class="anchored" data-anchor-id="why-not-just-a-plain-linear-ramp">Why not just a plain linear ramp?</h2>
<p>Because the data is <strong>heavy-tailed</strong> — a few countries emit thousands of megatonnes while most emit almost nothing. On a linear scale, <strong>195 of these 198 countries fall into the bottom fifth of the range</strong>, so a continuous ramp paints nearly the whole world one pale tone and spends its colour on two or three outliers. See for yourself — same data, default scale:</p>
<canvas id="co2linLive" width="700" height="480"></canvas>
<script>
(function () {
  var DATA = "https://www.canvasxpress.org/data/r/cX-CO2-dat.txt";
  function rows(text) {
    return text.trim().split("\n").map(function (line) { return line.split("\t"); });
  }
  function draw() {
    if (typeof CanvasXpress === "undefined") { return setTimeout(draw, 60); }
    fetch(DATA).then(function (r) { return r.text(); }).then(function (text) {
      var d = rows(text);
      var countries = d[0].slice(1);
      var values    = d[1].slice(1).map(Number);
      new CanvasXpress("co2linLive",
        { y: { vars: ["CO2"], smps: countries, data: [values] } },
        { graphType: "Map", colorBy: "CO2",
          topoJSON: "https://www.canvasxpress.org/data/maps/WORLD.json",
          mapId: "co2Linear", legendPosition: "left", theme: "solarized",
          title: "The same data on a plain linear ramp",
          subtitle: "195 of 198 countries sit in the bottom fifth of the scale - the map goes flat" });
    });
  }
  draw();
})();
</script>
<p>This is the single most common choropleth failure. The cure is <strong>classing</strong>:</p>
<ul>
<li><code>colorSpectrumBreaksMethod: "quantile"</code> — equal <em>counts</em> per class. Every colour is used, by construction. The right default for skewed data and for “which regions rank high/low” questions.</li>
<li><code>colorSpectrumBreaksMethod: "jenks"</code> — natural breaks that minimise within-class variance. Best when the data has genuine clusters with gaps between them; on smoothly heavy-tailed data like this it piles almost everything into the bottom class, so check the legend before you trust it.</li>
<li>Three to seven classes is the usable range — beyond that, readers cannot match colours to the legend.</li>
</ul>
</section>
<section id="choose-the-palette-on-purpose" class="level2">
<h2 class="anchored" data-anchor-id="choose-the-palette-on-purpose">Choose the palette on purpose</h2>
<p>The palette is the scale’s grammar, not decoration:</p>
<ul>
<li><p><strong>Sequential</strong> (dark → light of ordered hues, like viridis above) for a quantity that only goes up: counts, rates, concentrations.</p></li>
<li><p><strong>Diverging</strong> (two hues meeting at a neutral midpoint) when values are meaningful <em>above and below a reference</em>: change vs.&nbsp;last year, difference from a target, a signed index. Use a three-colour <code>colorSpectrum</code> and pin the midpoint:</p>
<div class="sourceCode" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode js code-with-copy"><code class="sourceCode javascript"><span id="cb3-1">colorBy<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Change"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb3-2">colorSpectrum<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2166ac"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#f7f7f7"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#b2182b"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span>  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// blue - neutral - red</span></span>
<span id="cb3-3">colorSpectrumZeroValue<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>                           <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// value mapped to the middle colour</span></span></code></pre></div>
<p>Never use a diverging palette for a purely positive quantity — the neutral midpoint invents a “normal” the data does not have. Viridis and the ColorBrewer ramps are colour-blind-safe and perceptually ordered; a rainbow ramp is neither. Keep the <em>same</em> scale across small multiples so maps stay comparable.</p></li>
</ul>
</section>
<section id="beyond-the-world-map" class="level2">
<h2 class="anchored" data-anchor-id="beyond-the-world-map">Beyond the world map</h2>
<ul>
<li><strong>Other boundaries.</strong> Point <code>topoJSON</code> at any shape file — US states, a country’s provinces, counties, custom districts. The join key is just the shape name.</li>
<li><strong>Projection.</strong> <code>mapProjection: "albers"</code> (equal-area) or <code>"mercator"</code>. Equal-area projections matter for choropleths: Mercator inflates high latitudes and exaggerates their visual weight.</li>
<li><strong>Categorical maps.</strong> Point <code>colorBy</code> at a categorical field for a qualitative choropleth with a discrete legend.</li>
<li><strong>Polish.</strong> <code>legendNumberFormat</code> formats the ticks, <code>legendInside</code> floats the legend over ocean, <code>showMapLabels</code> draws region names (best on few-region maps), <code>mapColor</code> sets the no-data fill so missing reads as missing, and <code>decorations</code> drops labelled markers on cities.</li>
</ul>
<p>The whole figure — data, boundaries, classing rule and palette — is one portable spec you can re-render from R or Python.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../choropleth-maps-in-r/">Choropleth maps in R</a></li>
<li><a href="../choropleth-maps-in-python/">Choropleth maps in Python</a></li>
<li><a href="../clustered-heatmap-in-javascript/">Clustered heatmaps in JavaScript</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
</ul>


</section>

 ]]></description>
  <category>JavaScript</category>
  <category>CanvasXpress</category>
  <category>maps</category>
  <category>choropleth</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/js/choropleth-maps-in-javascript/</guid>
  <pubDate>Thu, 08 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/js/choropleth-maps-in-javascript/thumbnail.png" medium="image" type="image/png" height="112" width="144"/>
</item>
<item>
  <title>Choropleth maps in Python with canvasxpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/python/choropleth-maps-in-python/</link>
  <description><![CDATA[ 




<p>A choropleth shades each region by a value — emissions, incidence, turnout, income. It is the most common map in data analysis and the easiest to get <em>subtly wrong</em>: most “my map is all one colour” complaints are not rendering bugs but scale bugs. Here we build a choropleth in Python with <a href="https://pypi.org/project/canvasxpress/">canvasxpress</a> that stays vivid and honest on exactly the kind of heavy-tailed data that flattens naive maps. The join and the colouring happen inside the render, so every figure is one portable spec you can re-run from Python, R or the browser.</p>
<section id="install" class="level2">
<h2 class="anchored" data-anchor-id="install">Install</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode bash code-with-copy"><code class="sourceCode bash"><span id="cb1-1"><span class="ex" style="color: null;
background-color: null;
font-style: inherit;">pip</span> install canvasxpress pandas</span></code></pre></div>
</section>
<section id="first-the-trap-colour-encodes-a-rate-not-a-count" class="level2">
<h2 class="anchored" data-anchor-id="first-the-trap-colour-encodes-a-rate-not-a-count">First, the trap: colour encodes a <em>rate</em>, not a <em>count</em></h2>
<p>A choropleth fills an <strong>area</strong>, and area is a size channel your eye cannot help reading. Shade regions by a raw count — total cases, total emissions, total sales — and big, populous regions light up simply because they are big and populous. You have drawn a population map with extra steps.</p>
<p>The fix is almost always to map a <strong>rate or density</strong>: cases per 100k, emissions per capita, sales per store. Reserve raw counts for a <em>proportional-symbol</em> map (a sized bubble at each centroid), where the size channel carries the count honestly. Decide which question you are answering before you pick the geometry — this one choice prevents most misleading maps.</p>
</section>
<section id="one-value-per-region" class="level2">
<h2 class="anchored" data-anchor-id="one-value-per-region">One value per region</h2>
<p>A choropleth needs exactly one measurement per shape. In canvasxpress the <strong>columns</strong> (<code>smps</code>) are the regions — they match the map by name — and each <strong>row</strong> (<code>vars</code>) is a variable you can colour by. Here it’s CO₂ emissions per country for 2018. We load a prepared table; swap it for your own (any <code>country → value</code> table works).</p>
<div id="1d78e58c" class="cell" data-execution_count="1">
<div class="sourceCode cell-code" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> pandas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">as</span> pd</span>
<span id="cb2-2"></span>
<span id="cb2-3">dat <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(</span>
<span id="cb2-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/r/cX-CO2-dat.txt"</span>,</span>
<span id="cb2-5">    sep<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, index_col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb2-6">)</span>
<span id="cb2-7">smp <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> pd.read_csv(</span>
<span id="cb2-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/r/cX-CO2-smp.txt"</span>,</span>
<span id="cb2-9">    sep<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="ch" style="color: #20794D;
background-color: null;
font-style: inherit;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, index_col<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,</span>
<span id="cb2-10">).reindex(dat.columns)        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># align annotation to the country order</span></span>
<span id="cb2-11"></span>
<span id="cb2-12"><span class="bu" style="color: null;
background-color: null;
font-style: inherit;">print</span>(dat.shape)              <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># (1, N): one row (CO2) x N countries</span></span>
<span id="cb2-13">dat.iloc[:, :<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>(1, 198)</code></pre>
</div>
<div class="cell-output cell-output-display" data-execution_count="1">
<div>


<table class="dataframe caption-top table table-sm table-striped small" data-quarto-postprocess="true" data-border="1">
<thead>
<tr class="header">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">Afghanistan</th>
<th data-quarto-table-cell-role="th">Albania</th>
<th data-quarto-table-cell-role="th">Algeria</th>
<th data-quarto-table-cell-role="th">Andorra</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td data-quarto-table-cell-role="th">CO2</td>
<td>10.452666</td>
<td>5.402999</td>
<td>164.309295</td>
<td>0.46421</td>
</tr>
</tbody>
</table>

</div>
</div>
</div>
</section>
<section id="the-map-quantile-classes-on-a-viridis-ramp" class="level2">
<h2 class="anchored" data-anchor-id="the-map-quantile-classes-on-a-viridis-ramp">The map: quantile classes on a viridis ramp</h2>
<p><code>y</code> carries the matrix (<code>vars</code> = the variable, <code>smps</code> = the countries, <code>data</code> = the values); the optional <code>x</code> block adds per-country annotations (continent, ISO code) for richer tooltips. The two choices that make this map <em>work</em> are in the colour scale: a seven-stop viridis <code>colorSpectrum</code>, and <code>colorSpectrumBreaksMethod = "quantile"</code>, which puts an equal number of countries in every colour class. On skewed data that guarantee is what keeps all seven colours on the map.</p>
<div id="f4223f77" class="cell" data-execution_count="2">
<div class="sourceCode cell-code" id="cb4" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.canvas <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CanvasXpress</span>
<span id="cb4-2"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> canvasxpress.render.jupyter <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> CXNoteBook</span>
<span id="cb4-3"><span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">from</span> IPython.display <span class="im" style="color: #00769E;
background-color: null;
font-style: inherit;">import</span> display</span>
<span id="cb4-4"></span>
<span id="cb4-5">data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb4-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"y"</span>: {</span>
<span id="cb4-7">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"vars"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(dat.index),            <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ["CO2"]</span></span>
<span id="cb4-8">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"smps"</span>: <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">list</span>(dat.columns),          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># country names</span></span>
<span id="cb4-9">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"data"</span>: dat.values.tolist(),        <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># [[values]]</span></span>
<span id="cb4-10">    },</span>
<span id="cb4-11">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"x"</span>: {</span>
<span id="cb4-12">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Continent"</span>: smp[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Continent"</span>].tolist(),</span>
<span id="cb4-13">        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Code"</span>:      smp[<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Code"</span>].tolist(),</span>
<span id="cb4-14">    },</span>
<span id="cb4-15">}</span>
<span id="cb4-16"></span>
<span id="cb4-17">config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb4-18">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Map"</span>,</span>
<span id="cb4-19">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"colorBy"</span>:   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CO2"</span>,</span>
<span id="cb4-20">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"topoJSON"</span>:  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/maps/WORLD.json"</span>,</span>
<span id="cb4-21">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mapId"</span>:     <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"co2Quantile"</span>,</span>
<span id="cb4-22">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"colorSpectrum"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#440154"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#443983"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#31688e"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#21918c"</span>,</span>
<span id="cb4-23">                      <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#35b779"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#90d743"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#fde725"</span>],</span>
<span id="cb4-24">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"colorSpectrumBreaksMethod"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"quantile"</span>,</span>
<span id="cb4-25">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mapColor"</span>:        <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d9dde3"</span>,</span>
<span id="cb4-26">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mapOutlineColor"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#ffffff"</span>,</span>
<span id="cb4-27">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"legendPosition"</span>:  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>,</span>
<span id="cb4-28">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>:    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CO2 emissions per country (2018)"</span>,</span>
<span id="cb4-29">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"subtitle"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Seven quantile classes: each colour holds about 28 of 198 countries"</span>,</span>
<span id="cb4-30">}</span>
<span id="cb4-31"></span>
<span id="cb4-32">cx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CanvasXpress(render_to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"co2quant"</span>, data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>data, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>config, width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">760</span>, height<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">520</span>)</span>
<span id="cb4-33"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> part <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> CXNoteBook(cx).render():</span>
<span id="cb4-34">    display(part)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="co2quant" width="760" height="520"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("co2quant");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart co2quant removed for re-rendering.");
  } else {
    console.log("Chart co2quant ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart co2quant could not be cleaned for re-rendering:", error);
}

var chart_co2quant = new CanvasXpress({"renderTo": "co2quant", "data": {"y": {"vars": ["CO2"], "smps": ["Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Anguilla", "Antigua & Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "British Virgin Islands", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Central African Republic", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo", "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia", "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Fiji", "Finland", "France", "French Polynesia", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Greece", "Greenland", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Moldova", "Mongolia", "Montenegro", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Democratic People's Republic of Korea", "The former Yugoslav Republic of Macedonia", "Norway", "Oman", "Pakistan", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Qatar", "Romania", "Russia", "Rwanda", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "Sao Tome and Principe", "Saudi Arabia", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "Republic of Korea", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Sweden", "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela", "Vietnam", "Yemen", "Zambia", "Zimbabwe"], "data": [[10.452666, 5.402999, 164.309295, 0.46421, 37.678605, 0.147145, 0.505574, 185.029897, 6.296603, 0.943234, 415.953947, 66.719678, 37.488394, 2.03001, 31.594487, 85.718805, 1.207134, 61.871676, 100.207836, 0.612205, 7.759753, 0.648945, 1.662172, 22.345503, 22.086102, 6.815418, 466.649304, 0.173555, 9.560399, 43.551599, 4.140342, 0.568028, 15.479031, 7.566796, 586.504635, 0.609509, 0.300478, 1.008035, 85.829114, 9956.568523, 92.228209, 0.245927, 3.518309, 0.072706, 8.249118, 17.718646, 26.084446, 7.332762, 104.411211, 2.231343, 34.65143, 0.389975, 25.305221, 41.817989, 251.460913, 6.018265, 5.90578, 0.708769, 17.710953, 16.184949, 2.123769, 45.849349, 331.725446, 0.780633, 4.803117, 0.56324, 9.862173, 755.362342, 14.479998, 71.797869, 0.511728, 0.278597, 19.411335, 3.032114, 0.308612, 2.342628, 3.366964, 10.470701, 42.505723, 49.628491, 3.674529, 2591.323739, 576.58439, 755.402186, 211.270294, 38.803394, 62.212641, 348.085029, 8.009662, 1135.688, 24.923803, 319.647412, 17.136703, 0.068879, 104.217567, 10.16888, 32.26245, 7.859287, 27.565431, 2.425558, 1.27446, 45.205986, 0.14375, 13.669492, 9.56852, 2.216456, 4.187806, 1.470252, 249.144498, 1.565092, 3.273276, 1.531581, 0.153065, 3.934804, 4.901611, 451.080829, 5.877784, 64.508256, 2.123147, 65.367444, 8.383478, 26.095603, 4.154302, 0.049746, 13.410432, 160.170147, 8.20904, 35.080341, 5.377193, 2.093847, 136.078346, 0.007653, 38.162935, 6.980909, 43.817657, 71.029916, 247.425382, 12.096333, 6.786146, 8.103032, 54.210259, 138.924391, 337.705742, 51.482481, 109.24468, 76.951219, 1691.360426, 1.080098, 0.011319, 0.249014, 0.362202, 0.079232, 0.264106, 0.267864, 0.126126, 576.757836, 46.0531, 0.60536, 0.987559, 38.28806, 36.087837, 14.487844, 0.298477, 0.658329, 634.934068, 1.539884, 269.654254, 22.973233, 22.372399, 2.551817, 41.766183, 36.895485, 25.877689, 273.104667, 7.473265, 11.501889, 292.452995, 0.520422, 3.167303, 0.164545, 37.865571, 30.357093, 419.194747, 78.034724, 0.01148, 5.384767, 231.694165, 188.541366, 380.138559, 5424.881502, 6.251839, 113.93837, 0.145412, 129.596274, 211.774129, 9.945288, 6.930094, 11.340575]]}, "x": {"Continent": ["Asia", "Europe", "Africa", "Europe", "Africa", "North America", "North America", "South America", "Asia", "North America", "Oceania", "Europe", "Europe", "North America", "Asia", "Asia", "North America", "Europe", "Europe", "North America", "Africa", "North America", "Asia", "South America", "Europe", "Africa", "South America", "North America", "Asia", "Europe", "Africa", "Africa", "Asia", "Africa", "North America", "Africa", "Africa", "Africa", "South America", "Asia", "South America", "Africa", "Africa", "Oceania", "Central America", "Europe", "North America", "Europe", "Europe", "Africa", "Europe", "Africa", "North America", "South America", "Africa", "Central America", "Africa", "Africa", "Europe", "Africa", "Oceania", "Europe", "Europe", "Oceania", "Africa", "Africa", "Asia", "Europe", "Africa", "Europe", "North America", "North America", "Central America", "Africa", "Africa", "South America", "North America", "Central America", "Asia", "Europe", "Europe", "Asia", "Asia", "Asia", "Asia", "Europe", "Asia", "Europe", "North America", "Asia", "Asia", "Asia", "Africa", "Oceania", "Asia", "Asia", "Asia", "Europe", "Asia", "Africa", "Africa", "Africa", "Europe", "Europe", "Europe", "Asia", "Africa", "Africa", "Asia", "Asia", "Africa", "Europe", "Oceania", "Africa", "Africa", "North America", "Europe", "Asia", "Europe", "Africa", "Africa", "Asia", "Africa", "Oceania", "Asia", "Europe", "Oceania", "Oceania", "Central America", "Africa", "Africa", "Oceania", "Asia", "Europe", "Europe", "Asia", "Asia", "Central America", "Oceania", "South America", "South America", "Asia", "Europe", "Europe", "Africa", "Europe", "Asia", "Africa", "Africa", "North America", "North America", "North America", "North America", "Oceania", "Africa", "Asia", "Europe", "Africa", "Africa", "Asia", "Europe", "Europe", "Oceania", "Africa", "Asia", "Africa", "Europe", "Asia", "Africa", "South America", "Europe", "Europe", "Asia", "Asia", "Asia", "Africa", "Asia", "Asia", "Africa", "Oceania", "North America", "Africa", "Asia", "Asia", "Oceania", "Africa", "Europe", "Asia", "Europe", "North America", "South America", "Asia", "Oceania", "South America", "Asia", "Asia", "Africa", "Africa"], "Code": ["AFG", "ALB", "DZA", "AND", "AGO", "AIA", "ATG", "ARG", "ARM", "ABW", "AUS", "AUT", "AZE", "BHS", "BHR", "BGD", "BRB", "BLR", "BEL", "BLZ", "BEN", "BMU", "BTN", "BOL", "BIH", "BWA", "BRA", "VGB", "BRN", "BGR", "BFA", "BDI", "KHM", "CMR", "CAN", "CPV", "CAF", "TCD", "CHL", "CHN", "COL", "COM", "COG", "COK", "CRI", "HRV", "CUB", "CYP", "CZE", "COD", "DNK", "DJI", "DOM", "ECU", "EGY", "SLV", "GNQ", "ERI", "EST", "ETH", "FJI", "FIN", "FRA", "PYF", "GAB", "GMB", "GEO", "DEU", "GHA", "GRC", "GRL", "GRD", "GTM", "GIN", "GNB", "GUY", "HTI", "HND", "HKG", "HUN", "ISL", "IND", "IDN", "IRN", "IRQ", "IRL", "ISR", "ITA", "JAM", "JPN", "JOR", "KAZ", "KEN", "KIR", "KWT", "KGZ", "LAO", "LVA", "LBN", "LSO", "LBR", "LBY", "LIE", "LTU", "LUX", "MAC", "MDG", "MWI", "MYS", "MDV", "MLI", "MLT", "MHL", "MRT", "MUS", "MEX", "MDA", "MNG", "MNE", "MAR", "MOZ", "MMR", "NAM", "NRU", "NPL", "NLD", "NCL", "NZL", "NIC", "NER", "NGA", "NIU", "PRK", "MKD", "NOR", "OMN", "PAK", "PAN", "PNG", "PRY", "PER", "PHL", "POL", "PRT", "QAT", "ROU", "RUS", "RWA", "SHN", "KNA", "LCA", "SPM", "VCT", "WSM", "STP", "SAU", "SRB", "SYC", "SLE", "SGP", "SVK", "SVN", "SLB", "SOM", "KOR", "SSD", "ESP", "LKA", "SDN", "SUR", "SWE", "CHE", "SYR", "TWN", "TJK", "TZA", "THA", "TLS", "TGO", "TON", "TTO", "TUN", "TUR", "TKM", "TUV", "UGA", "UKR", "ARE", "GBR", "USA", "URY", "UZB", "VUT", "VEN", "VNM", "YEM", "ZMB", "ZWE"]}, "z": null}, "config": {"graphType": "Map", "colorBy": "CO2", "topoJSON": "https://www.canvasxpress.org/data/maps/WORLD.json", "mapId": "co2Quantile", "colorSpectrum": ["#440154", "#443983", "#31688e", "#21918c", "#35b779", "#90d743", "#fde725"], "colorSpectrumBreaksMethod": "quantile", "mapColor": "#d9dde3", "mapOutlineColor": "#ffffff", "legendPosition": "bottom", "title": "CO2 emissions per country (2018)", "subtitle": "Seven quantile classes: each colour holds about 28 of 198 countries"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
<p>Every band of the ramp is doing work: the darkest purples are the smallest emitters, the yellows the largest, and the legend’s break values tell you the class edges are <em>data-driven</em>, not evenly spaced. Hover any country for its name, continent and value.</p>
</section>
<section id="why-not-just-a-plain-linear-ramp" class="level2">
<h2 class="anchored" data-anchor-id="why-not-just-a-plain-linear-ramp">Why not just a plain linear ramp?</h2>
<p>Because the data is <strong>heavy-tailed</strong> — a few countries emit thousands of megatonnes while most emit almost nothing. On a linear scale, <strong>195 of these 198 countries fall into the bottom fifth of the range</strong>, so a continuous ramp paints nearly the whole world one pale tone and spends its colour on two or three outliers:</p>
<div id="54fe8306" class="cell" data-execution_count="3">
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1">linear <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb5-2">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"graphType"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Map"</span>,</span>
<span id="cb5-3">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"colorBy"</span>:   <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CO2"</span>,</span>
<span id="cb5-4">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"topoJSON"</span>:  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/maps/WORLD.json"</span>,</span>
<span id="cb5-5">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"mapId"</span>:     <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"co2Linear"</span>,</span>
<span id="cb5-6">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"legendPosition"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"left"</span>,</span>
<span id="cb5-7">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"theme"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"solarized"</span>,</span>
<span id="cb5-8">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"title"</span>:    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"The same data on a plain linear ramp"</span>,</span>
<span id="cb5-9">    <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"subtitle"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"195 of 198 countries sit in the bottom fifth of the scale - the map goes flat"</span>,</span>
<span id="cb5-10">}</span>
<span id="cb5-11"></span>
<span id="cb5-12">cx <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> CanvasXpress(render_to<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"co2lin"</span>, data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>data, config<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span>linear, width<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">700</span>, height<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">480</span>)</span>
<span id="cb5-13"><span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">for</span> part <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">in</span> CXNoteBook(cx).render():</span>
<span id="cb5-14">    display(part)</span></code></pre></div>
<div class="cell-output cell-output-display">

</div>
<div class="cell-output cell-output-display">

<div style="display: grid; grid-template-columns: repeat(1, 1fr); gap: 10px; width: 100%;">
  <div><canvas id="co2lin" width="700" height="480"></canvas></div>
</div>
</div>
<div class="cell-output cell-output-display">
<script type="application/javascript">

// 1. First, handle CSS Insertion and wait for it to be completely ready
new Promise((cssResolve, cssReject) => {
    const cssUrl = "https://www.canvasxpress.org/dist/canvasXpress.css";
    let existingLink = document.querySelector(`head link[href="${cssUrl}"]`);

    if (!existingLink) {
        const link = document.createElement("link");
        link.rel = "stylesheet";
        link.type = "text/css";
        link.href = cssUrl;
        link.onload = () => {
            link.dataset.state = "loaded";
            link.dispatchEvent(new Event("assetLoaded"));
            cssResolve();
        };
        link.onerror = () => {
            link.dataset.state = "failed";
            link.dispatchEvent(new Event("assetFailed"));
            cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
        };
        document.head.appendChild(link);
    } else if (existingLink.dataset.state === "loaded") {
        cssResolve();
    } else if (existingLink.dataset.state === "failed") {
        cssReject(new Error(`Failed to load CSS: ${cssUrl}`));
    } else {
        // Safe queueing for subsequent runs initiated while CSS is downloading
        existingLink.addEventListener('assetLoaded', () => cssResolve(), { once: true });
        existingLink.addEventListener('assetFailed', () => cssReject(new Error(`Failed to load CSS: ${cssUrl}`)), { once: true });
    }
})
.then(() => {
    // 2. CSS is guaranteed ready. Now handle JS Insertion
    return new Promise((jsResolve, jsReject) => {
        const scriptUrl = 'https://www.canvasxpress.org/dist/canvasXpress.min.js';
        let existingScript = document.querySelector(`script[src="${scriptUrl}"]`);

        if (existingScript) {
            if (existingScript.dataset.state === "loaded") {
                jsResolve();
            } else if (existingScript.dataset.state === "failed") {
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            } else {
                // Safe queueing for subsequent runs initiated while JS is downloading
                existingScript.addEventListener('assetLoaded', () => jsResolve(), { once: true });
                existingScript.addEventListener('assetFailed', () => jsReject(new Error(`Failed to load script: ${scriptUrl}`)), { once: true });
            }
        } else {
            const script = document.createElement("script");
            script.type = "text/javascript";
            script.src = scriptUrl;
            script.dataset.state = "loading";

            script.onload = () => {
                script.dataset.state = "loaded";
                script.dispatchEvent(new Event("assetLoaded"));
                jsResolve();
            };
            script.onerror = () => {
                script.dataset.state = "failed";
                script.dispatchEvent(new Event("assetFailed"));
                jsReject(new Error(`Failed to load script: ${scriptUrl}`));
            };
            document.head.appendChild(script);
        }
    });
})
.then(() => { 
    // 3. Both CSS and JS are ready in order. Run user payload.
    
try {
  // 1. Get the chart object using the HTML element ID
  let myChart = CanvasXpress.getObject("co2lin");
  
  // 2. Check if the chart exists before trying to delete it
  if (myChart) {
    myChart.destroy();
    console.log("Chart co2lin removed for re-rendering.");
  } else {
    console.log("Chart co2lin ready for rendering.");
  }
} catch (error) {
  // 3. Handle any unexpected errors safely
  console.error("Chart co2lin could not be cleaned for re-rendering:", error);
}

var chart_co2lin = new CanvasXpress({"renderTo": "co2lin", "data": {"y": {"vars": ["CO2"], "smps": ["Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Anguilla", "Antigua & Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "British Virgin Islands", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Central African Republic", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo", "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czechia", "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Fiji", "Finland", "France", "French Polynesia", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Greece", "Greenland", "Grenada", "Guatemala", "Guinea", "Guinea-Bissau", "Guyana", "Haiti", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica", "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Moldova", "Mongolia", "Montenegro", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Democratic People's Republic of Korea", "The former Yugoslav Republic of Macedonia", "Norway", "Oman", "Pakistan", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Qatar", "Romania", "Russia", "Rwanda", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "Sao Tome and Principe", "Saudi Arabia", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "Republic of Korea", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Sweden", "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela", "Vietnam", "Yemen", "Zambia", "Zimbabwe"], "data": [[10.452666, 5.402999, 164.309295, 0.46421, 37.678605, 0.147145, 0.505574, 185.029897, 6.296603, 0.943234, 415.953947, 66.719678, 37.488394, 2.03001, 31.594487, 85.718805, 1.207134, 61.871676, 100.207836, 0.612205, 7.759753, 0.648945, 1.662172, 22.345503, 22.086102, 6.815418, 466.649304, 0.173555, 9.560399, 43.551599, 4.140342, 0.568028, 15.479031, 7.566796, 586.504635, 0.609509, 0.300478, 1.008035, 85.829114, 9956.568523, 92.228209, 0.245927, 3.518309, 0.072706, 8.249118, 17.718646, 26.084446, 7.332762, 104.411211, 2.231343, 34.65143, 0.389975, 25.305221, 41.817989, 251.460913, 6.018265, 5.90578, 0.708769, 17.710953, 16.184949, 2.123769, 45.849349, 331.725446, 0.780633, 4.803117, 0.56324, 9.862173, 755.362342, 14.479998, 71.797869, 0.511728, 0.278597, 19.411335, 3.032114, 0.308612, 2.342628, 3.366964, 10.470701, 42.505723, 49.628491, 3.674529, 2591.323739, 576.58439, 755.402186, 211.270294, 38.803394, 62.212641, 348.085029, 8.009662, 1135.688, 24.923803, 319.647412, 17.136703, 0.068879, 104.217567, 10.16888, 32.26245, 7.859287, 27.565431, 2.425558, 1.27446, 45.205986, 0.14375, 13.669492, 9.56852, 2.216456, 4.187806, 1.470252, 249.144498, 1.565092, 3.273276, 1.531581, 0.153065, 3.934804, 4.901611, 451.080829, 5.877784, 64.508256, 2.123147, 65.367444, 8.383478, 26.095603, 4.154302, 0.049746, 13.410432, 160.170147, 8.20904, 35.080341, 5.377193, 2.093847, 136.078346, 0.007653, 38.162935, 6.980909, 43.817657, 71.029916, 247.425382, 12.096333, 6.786146, 8.103032, 54.210259, 138.924391, 337.705742, 51.482481, 109.24468, 76.951219, 1691.360426, 1.080098, 0.011319, 0.249014, 0.362202, 0.079232, 0.264106, 0.267864, 0.126126, 576.757836, 46.0531, 0.60536, 0.987559, 38.28806, 36.087837, 14.487844, 0.298477, 0.658329, 634.934068, 1.539884, 269.654254, 22.973233, 22.372399, 2.551817, 41.766183, 36.895485, 25.877689, 273.104667, 7.473265, 11.501889, 292.452995, 0.520422, 3.167303, 0.164545, 37.865571, 30.357093, 419.194747, 78.034724, 0.01148, 5.384767, 231.694165, 188.541366, 380.138559, 5424.881502, 6.251839, 113.93837, 0.145412, 129.596274, 211.774129, 9.945288, 6.930094, 11.340575]]}, "x": {"Continent": ["Asia", "Europe", "Africa", "Europe", "Africa", "North America", "North America", "South America", "Asia", "North America", "Oceania", "Europe", "Europe", "North America", "Asia", "Asia", "North America", "Europe", "Europe", "North America", "Africa", "North America", "Asia", "South America", "Europe", "Africa", "South America", "North America", "Asia", "Europe", "Africa", "Africa", "Asia", "Africa", "North America", "Africa", "Africa", "Africa", "South America", "Asia", "South America", "Africa", "Africa", "Oceania", "Central America", "Europe", "North America", "Europe", "Europe", "Africa", "Europe", "Africa", "North America", "South America", "Africa", "Central America", "Africa", "Africa", "Europe", "Africa", "Oceania", "Europe", "Europe", "Oceania", "Africa", "Africa", "Asia", "Europe", "Africa", "Europe", "North America", "North America", "Central America", "Africa", "Africa", "South America", "North America", "Central America", "Asia", "Europe", "Europe", "Asia", "Asia", "Asia", "Asia", "Europe", "Asia", "Europe", "North America", "Asia", "Asia", "Asia", "Africa", "Oceania", "Asia", "Asia", "Asia", "Europe", "Asia", "Africa", "Africa", "Africa", "Europe", "Europe", "Europe", "Asia", "Africa", "Africa", "Asia", "Asia", "Africa", "Europe", "Oceania", "Africa", "Africa", "North America", "Europe", "Asia", "Europe", "Africa", "Africa", "Asia", "Africa", "Oceania", "Asia", "Europe", "Oceania", "Oceania", "Central America", "Africa", "Africa", "Oceania", "Asia", "Europe", "Europe", "Asia", "Asia", "Central America", "Oceania", "South America", "South America", "Asia", "Europe", "Europe", "Africa", "Europe", "Asia", "Africa", "Africa", "North America", "North America", "North America", "North America", "Oceania", "Africa", "Asia", "Europe", "Africa", "Africa", "Asia", "Europe", "Europe", "Oceania", "Africa", "Asia", "Africa", "Europe", "Asia", "Africa", "South America", "Europe", "Europe", "Asia", "Asia", "Asia", "Africa", "Asia", "Asia", "Africa", "Oceania", "North America", "Africa", "Asia", "Asia", "Oceania", "Africa", "Europe", "Asia", "Europe", "North America", "South America", "Asia", "Oceania", "South America", "Asia", "Asia", "Africa", "Africa"], "Code": ["AFG", "ALB", "DZA", "AND", "AGO", "AIA", "ATG", "ARG", "ARM", "ABW", "AUS", "AUT", "AZE", "BHS", "BHR", "BGD", "BRB", "BLR", "BEL", "BLZ", "BEN", "BMU", "BTN", "BOL", "BIH", "BWA", "BRA", "VGB", "BRN", "BGR", "BFA", "BDI", "KHM", "CMR", "CAN", "CPV", "CAF", "TCD", "CHL", "CHN", "COL", "COM", "COG", "COK", "CRI", "HRV", "CUB", "CYP", "CZE", "COD", "DNK", "DJI", "DOM", "ECU", "EGY", "SLV", "GNQ", "ERI", "EST", "ETH", "FJI", "FIN", "FRA", "PYF", "GAB", "GMB", "GEO", "DEU", "GHA", "GRC", "GRL", "GRD", "GTM", "GIN", "GNB", "GUY", "HTI", "HND", "HKG", "HUN", "ISL", "IND", "IDN", "IRN", "IRQ", "IRL", "ISR", "ITA", "JAM", "JPN", "JOR", "KAZ", "KEN", "KIR", "KWT", "KGZ", "LAO", "LVA", "LBN", "LSO", "LBR", "LBY", "LIE", "LTU", "LUX", "MAC", "MDG", "MWI", "MYS", "MDV", "MLI", "MLT", "MHL", "MRT", "MUS", "MEX", "MDA", "MNG", "MNE", "MAR", "MOZ", "MMR", "NAM", "NRU", "NPL", "NLD", "NCL", "NZL", "NIC", "NER", "NGA", "NIU", "PRK", "MKD", "NOR", "OMN", "PAK", "PAN", "PNG", "PRY", "PER", "PHL", "POL", "PRT", "QAT", "ROU", "RUS", "RWA", "SHN", "KNA", "LCA", "SPM", "VCT", "WSM", "STP", "SAU", "SRB", "SYC", "SLE", "SGP", "SVK", "SVN", "SLB", "SOM", "KOR", "SSD", "ESP", "LKA", "SDN", "SUR", "SWE", "CHE", "SYR", "TWN", "TJK", "TZA", "THA", "TLS", "TGO", "TON", "TTO", "TUN", "TUR", "TKM", "TUV", "UGA", "UKR", "ARE", "GBR", "USA", "URY", "UZB", "VUT", "VEN", "VNM", "YEM", "ZMB", "ZWE"]}, "z": null}, "config": {"graphType": "Map", "colorBy": "CO2", "topoJSON": "https://www.canvasxpress.org/data/maps/WORLD.json", "mapId": "co2Linear", "legendPosition": "left", "theme": "solarized", "title": "The same data on a plain linear ramp", "subtitle": "195 of 198 countries sit in the bottom fifth of the scale - the map goes flat"}, "events": null}); 
;

 
})
.catch((error) => {
    console.error("CanvasXpress injection failed:", error);
});


</script>
</div>
</div>
<p>This is the single most common choropleth failure. The cure is <strong>classing</strong>:</p>
<ul>
<li><code>"colorSpectrumBreaksMethod": "quantile"</code> — equal <em>counts</em> per class. Every colour is used, by construction. The right default for skewed data and for “which regions rank high/low” questions.</li>
<li><code>"colorSpectrumBreaksMethod": "jenks"</code> — natural breaks that minimise within-class variance. Best when the data has genuine clusters with gaps between them; on smoothly heavy-tailed data like this it piles almost everything into the bottom class, so check the legend before you trust it.</li>
<li>Three to seven classes is the usable range — beyond that, readers cannot match colours to the legend.</li>
</ul>
</section>
<section id="choose-the-palette-on-purpose" class="level2">
<h2 class="anchored" data-anchor-id="choose-the-palette-on-purpose">Choose the palette on purpose</h2>
<p>The palette is the scale’s grammar, not decoration:</p>
<ul>
<li><p><strong>Sequential</strong> (dark → light of ordered hues, like viridis above) for a quantity that only goes up: counts, rates, concentrations.</p></li>
<li><p><strong>Diverging</strong> (two hues meeting at a neutral midpoint) when values are meaningful <em>above and below a reference</em>: change vs.&nbsp;last year, difference from a target, a signed index. Give a three-colour <code>colorSpectrum</code> and pin the midpoint with <code>colorSpectrumZeroValue</code>:</p>
<div class="sourceCode" id="cb6" style="background: #f1f3f5;"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"colorBy"</span>: <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Change"</span>,</span>
<span id="cb6-2"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"colorSpectrum"</span>: [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2166ac"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#f7f7f7"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#b2182b"</span>],  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># blue - neutral - red</span></span>
<span id="cb6-3"><span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">"colorSpectrumZeroValue"</span>: <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>,                          <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># value mapped to the middle colour</span></span></code></pre></div>
<p>Never use a diverging palette for a purely positive quantity — the neutral midpoint invents a “normal” the data does not have.</p></li>
</ul>
<p>Viridis and the ColorBrewer ramps are colour-blind-safe and perceptually ordered; a rainbow ramp is neither, so readers cannot tell which end means “more”. Keep the <em>same</em> scale across small multiples so maps stay comparable.</p>
</section>
<section id="polish-legend-labels-and-base-styling" class="level2">
<h2 class="anchored" data-anchor-id="polish-legend-labels-and-base-styling">Polish: legend, labels and base styling</h2>
<ul>
<li><code>subtitle</code> / <code>source</code> — caption units and provenance.</li>
<li><code>"legendNumberFormat": {"style": "decimal", "decimals": 1, "suffix": "%"}</code> — format legend ticks.</li>
<li><code>mapColor</code> / <code>mapOutlineColor</code> — the fill for <strong>no-data</strong> regions (a neutral grey) and the shape borders, so missing data reads as missing rather than as a value.</li>
<li><code>"showMapLabels": True</code> — draw region names (best on few-region maps; clutters a world map).</li>
<li><code>"legendInside": True</code> — float the legend over empty ocean to reclaim width.</li>
</ul>
</section>
<section id="beyond-the-world-map" class="level2">
<h2 class="anchored" data-anchor-id="beyond-the-world-map">Beyond the world map</h2>
<ul>
<li><strong>Other boundaries.</strong> Point <code>topoJSON</code> at any shape file — US states, a country’s provinces, counties, custom districts. The join key is just the shape name.</li>
<li><strong>Projection.</strong> <code>"mapProjection": "albers"</code> (equal-area) or <code>"mercator"</code>. Equal-area projections matter for choropleths: Mercator inflates high latitudes and exaggerates their visual weight.</li>
<li><strong>Categorical maps.</strong> Point <code>colorBy</code> at a categorical column for a qualitative choropleth with a discrete legend.</li>
<li><strong>Markers.</strong> Add <code>decorations</code> to drop labelled points on cities or call out specific regions.</li>
</ul>
<p>The whole figure — data, boundaries, classing rule and palette — is one portable spec you can store, validate and re-render from R or JavaScript.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../choropleth-maps-in-r/">Choropleth maps in R</a></li>
<li><a href="../choropleth-maps-in-javascript/">Choropleth maps in JavaScript</a></li>
<li><a href="../clustered-heatmap-in-python/">Clustered heatmaps in Python</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
</ul>


</section>

 ]]></description>
  <category>Python</category>
  <category>canvasxpress</category>
  <category>maps</category>
  <category>choropleth</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/python/choropleth-maps-in-python/</guid>
  <pubDate>Wed, 07 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/python/choropleth-maps-in-python/thumbnail.png" medium="image" type="image/png" height="112" width="144"/>
</item>
<item>
  <title>Choropleth maps in R with canvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/r/choropleth-maps-in-r/</link>
  <description><![CDATA[ 




<p>A choropleth shades each region by a value — emissions, incidence, turnout, income. It is the most common map in data analysis and the easiest to get <em>subtly wrong</em>: most “my map is all one colour” complaints are not rendering bugs but scale bugs. This post builds a choropleth in R with <a href="https://canvasxpress.org">canvasXpress</a> that stays vivid and honest on exactly the kind of heavy-tailed data that flattens naive maps. The join and the colouring happen inside the render, so every figure is one portable spec you can re-run from R, Python or the browser.</p>
<section id="first-the-trap-colour-encodes-a-rate-not-a-count" class="level2">
<h2 class="anchored" data-anchor-id="first-the-trap-colour-encodes-a-rate-not-a-count">First, the trap: colour encodes a <em>rate</em>, not a <em>count</em></h2>
<p>A choropleth fills an <strong>area</strong>, and area is a size channel your eye cannot help reading. Shade countries by a raw count — total cases, total emissions, total sales — and big, populous regions light up simply because they are big and populous. You have drawn a population map with extra steps.</p>
<p>The fix is almost always to map a <strong>rate or density</strong>: cases per 100k, emissions per capita, sales per store. Reserve raw counts for a <em>proportional-symbol</em> map (a sized bubble at each centroid), where the size channel carries the count honestly. Decide which question you are answering before you pick the geometry — this one choice prevents most misleading maps.</p>
</section>
<section id="one-value-per-region" class="level2">
<h2 class="anchored" data-anchor-id="one-value-per-region">One value per region</h2>
<p>A choropleth needs exactly one measurement per shape. In canvasXpress the <strong>columns</strong> are the regions (they match the map by name) and the <strong>row</strong> is the variable you colour by — here CO₂ emissions per country for 2018. Load a prepared table; swap it for your own (any <code>country → value</code> table works).</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb1-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">library</span>(canvasXpress)</span>
<span id="cb1-2"></span>
<span id="cb1-3">y <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read.table</span>(</span>
<span id="cb1-4">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/r/cX-CO2-dat.txt"</span>,</span>
<span id="cb1-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quote =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb1-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">check.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stringsAsFactors =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb1-7">)</span>
<span id="cb1-8"></span>
<span id="cb1-9"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">dim</span>(y)              <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># 1 row (CO2) x N countries</span></span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>[1]   1 198</code></pre>
</div>
<div class="sourceCode cell-code" id="cb3" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb3-1">y[, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span><span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>]</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>    Afghanistan  Albania  Algeria Andorra
CO2    10.45267 5.402999 164.3093 0.46421</code></pre>
</div>
</div>
<p>The single row is the variable (<code>CO2</code>); each column name is a country that must match a shape in the map. An optional <strong>sample annotation</strong> table (rows = countries) rides along for richer tooltips and legends — here the continent and ISO code.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb5" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb5-1">x <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">read.table</span>(</span>
<span id="cb5-2">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/r/cX-CO2-smp.txt"</span>,</span>
<span id="cb5-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">header =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">sep =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span><span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">\t</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">quote =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">row.names =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>,</span>
<span id="cb5-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">check.names =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">stringsAsFactors =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">FALSE</span></span>
<span id="cb5-5">)</span>
<span id="cb5-6"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">head</span>(x)</span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>            Code     Continent     Country
Afghanistan  AFG          Asia Afghanistan
Albania      ALB        Europe     Albania
Algeria      DZA        Africa     Algeria
Andorra      AND        Europe     Andorra
Angola       AGO        Africa      Angola
Anguilla     AIA North America    Anguilla</code></pre>
</div>
</div>
</section>
<section id="the-map-quantile-classes-computed-in-r-painted-by-the-map" class="level2">
<h2 class="anchored" data-anchor-id="the-map-quantile-classes-computed-in-r-painted-by-the-map">The map: quantile classes computed in R, painted by the map</h2>
<p><code>graphType = "Map"</code> with a <code>topoJSON</code> of world boundaries draws the shapes and joins the countries by name — no manual merge, no projection math. The statistics stay in R, where they belong: we cut the values into <strong>seven quantile classes</strong> with <code>quantile()</code> + <code>cut()</code>, so each class holds an equal number of countries (~28 of 198), then colour by that classed annotation with a viridis palette. On skewed data that equal-count guarantee is what keeps all seven colours on the map.</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb7" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb7-1">vals   <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.numeric</span>(y[<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, ])</span>
<span id="cb7-2">breaks <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">unique</span>(<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">quantile</span>(vals, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">probs =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">seq</span>(<span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>, <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">length.out =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">8</span>)))</span>
<span id="cb7-3">cls    <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">cut</span>(vals, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">breaks =</span> breaks, <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">include.lowest =</span> <span class="cn" style="color: #8f5902;
background-color: null;
font-style: inherit;">TRUE</span>)</span>
<span id="cb7-4">x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Emissions <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">&lt;-</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">sprintf</span>(</span>
<span id="cb7-5">  <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Q%d: %s"</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.integer</span>(cls),</span>
<span id="cb7-6">  <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gsub</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">","</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">" - "</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">gsub</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"[][()]"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">""</span>, <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">levels</span>(cls)))[<span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">as.integer</span>(cls)]</span>
<span id="cb7-7">)</span>
<span id="cb7-8"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">table</span>(x<span class="sc" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">$</span>Emissions)   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># ~28 countries per class</span></span></code></pre></div>
<div class="cell-output cell-output-stdout">
<pre><code>
Q1: 0.00765 - 0.564    Q2: 0.564 - 2.69      Q3: 2.69 - 7.8      Q4: 7.8 - 22.4 
                 29                  28                  28                  28 
      Q5: 22.4 - 46        Q6: 46 - 208  Q7: 208 - 9.96e+03 
                 28                  28                  29 </code></pre>
</div>
</div>
<div class="cell">
<div class="sourceCode cell-code" id="cb9" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb9-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">canvasXpress</span>(</span>
<span id="cb9-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data      =</span> y,</span>
<span id="cb9-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">smpAnnot  =</span> x,</span>
<span id="cb9-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Map"</span>,</span>
<span id="cb9-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colorBy   =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Emissions"</span>,</span>
<span id="cb9-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">topoJSON  =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/maps/WORLD.json"</span>,</span>
<span id="cb9-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mapId     =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"co2Quantile"</span>,</span>
<span id="cb9-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colors =</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#440154"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#443983"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#31688e"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#21918c"</span>,</span>
<span id="cb9-9">                <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#35b779"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#90d743"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#fde725"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d9dde3"</span>),</span>
<span id="cb9-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mapColor        =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#d9dde3"</span>,</span>
<span id="cb9-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mapOutlineColor =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#ffffff"</span>,</span>
<span id="cb9-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legendPosition  =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"bottom"</span>,</span>
<span id="cb9-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legendColumns   =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">4</span>,</span>
<span id="cb9-14">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title    =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CO2 emissions per country (2018)"</span>,</span>
<span id="cb9-15">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">subtitle =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Seven quantile classes computed in R: each colour holds about 28 of 198 countries"</span>,</span>
<span id="cb9-16">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width  =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">760</span>,</span>
<span id="cb9-17">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">560</span></span>
<span id="cb9-18">)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-f5120841cd0cc6fc003d" style="width:100%;height:478px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-f5120841cd0cc6fc003d">{"x":{"data":{"y":{"vars":["CO2"],"smps":["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua & Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia and Herzegovina","Botswana","Brazil","British Virgin Islands","Brunei Darussalam","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Canada","Cape Verde","Central African Republic","Chad","Chile","China","Colombia","Comoros","Congo","Cook Islands","Costa Rica","Croatia","Cuba","Cyprus","Czechia","Democratic Republic of the Congo","Denmark","Djibouti","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea","Eritrea","Estonia","Ethiopia","Fiji","Finland","France","French Polynesia","Gabon","Gambia","Georgia","Germany","Ghana","Greece","Greenland","Grenada","Guatemala","Guinea","Guinea-Bissau","Guyana","Haiti","Honduras","Hong Kong","Hungary","Iceland","India","Indonesia","Iran","Iraq","Ireland","Israel","Italy","Jamaica","Japan","Jordan","Kazakhstan","Kenya","Kiribati","Kuwait","Kyrgyzstan","Lao People's Democratic Republic","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macao","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Marshall Islands","Mauritania","Mauritius","Mexico","Moldova","Mongolia","Montenegro","Morocco","Mozambique","Myanmar","Namibia","Nauru","Nepal","Netherlands","New Caledonia","New Zealand","Nicaragua","Niger","Nigeria","Niue","Democratic People's Republic of Korea","The former Yugoslav Republic of Macedonia","Norway","Oman","Pakistan","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal","Qatar","Romania","Russia","Rwanda","Saint Helena","Saint Kitts and Nevis","Saint Lucia","Saint Pierre and Miquelon","Saint Vincent and the Grenadines","Samoa","Sao Tome and Principe","Saudi Arabia","Serbia","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","Solomon Islands","Somalia","Republic of Korea","South Sudan","Spain","Sri Lanka","Sudan","Suriname","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor-Leste","Togo","Tonga","Trinidad and Tobago","Tunisia","Turkey","Turkmenistan","Tuvalu","Uganda","Ukraine","United Arab Emirates","United Kingdom","United States","Uruguay","Uzbekistan","Vanuatu","Venezuela","Vietnam","Yemen","Zambia","Zimbabwe"],"data":[[10.45,5.403,164.3,0.4642,37.68,0.1471,0.5056,185,6.297,0.9432,416,66.72,37.49,2.03,31.59,85.72,1.207,61.87,100.2,0.6122,7.76,0.6489,1.662,22.35,22.09,6.815,466.6,0.1736,9.56,43.55,4.14,0.568,15.48,7.567,586.5,0.6095,0.3005,1.008,85.83,9957,92.23,0.2459,3.518,0.07271,8.249,17.72,26.08,7.333,104.4,2.231,34.65,0.39,25.31,41.82,251.5,6.018,5.906,0.7088,17.71,16.18,2.124,45.85,331.7,0.7806,4.803,0.5632,9.862,755.4,14.48,71.8,0.5117,0.2786,19.41,3.032,0.3086,2.343,3.367,10.47,42.51,49.63,3.675,2591,576.6,755.4,211.3,38.8,62.21,348.1,8.01,1136,24.92,319.6,17.14,0.06888,104.2,10.17,32.26,7.859,27.57,2.426,1.274,45.21,0.1437,13.67,9.569,2.216,4.188,1.47,249.1,1.565,3.273,1.532,0.1531,3.935,4.902,451.1,5.878,64.51,2.123,65.37,8.383,26.1,4.154,0.04975,13.41,160.2,8.209,35.08,5.377,2.094,136.1,0.007653,38.16,6.981,43.82,71.03,247.4,12.1,6.786,8.103,54.21,138.9,337.7,51.48,109.2,76.95,1691,1.08,0.01132,0.249,0.3622,0.07923,0.2641,0.2679,0.1261,576.8,46.05,0.6054,0.9876,38.29,36.09,14.49,0.2985,0.6583,634.9,1.54,269.7,22.97,22.37,2.552,41.77,36.9,25.88,273.1,7.473,11.5,292.5,0.5204,3.167,0.1645,37.87,30.36,419.2,78.03,0.01148,5.385,231.7,188.5,380.1,5425,6.252,113.9,0.1454,129.6,211.8,9.945,6.93,11.34]]},"x":{"Code":["AFG","ALB","DZA","AND","AGO","AIA","ATG","ARG","ARM","ABW","AUS","AUT","AZE","BHS","BHR","BGD","BRB","BLR","BEL","BLZ","BEN","BMU","BTN","BOL","BIH","BWA","BRA","VGB","BRN","BGR","BFA","BDI","KHM","CMR","CAN","CPV","CAF","TCD","CHL","CHN","COL","COM","COG","COK","CRI","HRV","CUB","CYP","CZE","COD","DNK","DJI","DOM","ECU","EGY","SLV","GNQ","ERI","EST","ETH","FJI","FIN","FRA","PYF","GAB","GMB","GEO","DEU","GHA","GRC","GRL","GRD","GTM","GIN","GNB","GUY","HTI","HND","HKG","HUN","ISL","IND","IDN","IRN","IRQ","IRL","ISR","ITA","JAM","JPN","JOR","KAZ","KEN","KIR","KWT","KGZ","LAO","LVA","LBN","LSO","LBR","LBY","LIE","LTU","LUX","MAC","MDG","MWI","MYS","MDV","MLI","MLT","MHL","MRT","MUS","MEX","MDA","MNG","MNE","MAR","MOZ","MMR","NAM","NRU","NPL","NLD","NCL","NZL","NIC","NER","NGA","NIU","PRK","MKD","NOR","OMN","PAK","PAN","PNG","PRY","PER","PHL","POL","PRT","QAT","ROU","RUS","RWA","SHN","KNA","LCA","SPM","VCT","WSM","STP","SAU","SRB","SYC","SLE","SGP","SVK","SVN","SLB","SOM","KOR","SSD","ESP","LKA","SDN","SUR","SWE","CHE","SYR","TWN","TJK","TZA","THA","TLS","TGO","TON","TTO","TUN","TUR","TKM","TUV","UGA","UKR","ARE","GBR","USA","URY","UZB","VUT","VEN","VNM","YEM","ZMB","ZWE"],"Continent":["Asia","Europe","Africa","Europe","Africa","North America","North America","South America","Asia","North America","Oceania","Europe","Europe","North America","Asia","Asia","North America","Europe","Europe","North America","Africa","North America","Asia","South America","Europe","Africa","South America","North America","Asia","Europe","Africa","Africa","Asia","Africa","North America","Africa","Africa","Africa","South America","Asia","South America","Africa","Africa","Oceania","Central America","Europe","North America","Europe","Europe","Africa","Europe","Africa","North America","South America","Africa","Central America","Africa","Africa","Europe","Africa","Oceania","Europe","Europe","Oceania","Africa","Africa","Asia","Europe","Africa","Europe","North America","North America","Central America","Africa","Africa","South America","North America","Central America","Asia","Europe","Europe","Asia","Asia","Asia","Asia","Europe","Asia","Europe","North America","Asia","Asia","Asia","Africa","Oceania","Asia","Asia","Asia","Europe","Asia","Africa","Africa","Africa","Europe","Europe","Europe","Asia","Africa","Africa","Asia","Asia","Africa","Europe","Oceania","Africa","Africa","North America","Europe","Asia","Europe","Africa","Africa","Asia","Africa","Oceania","Asia","Europe","Oceania","Oceania","Central America","Africa","Africa","Oceania","Asia","Europe","Europe","Asia","Asia","Central America","Oceania","South America","South America","Asia","Europe","Europe","Africa","Europe","Asia","Africa","Africa","North America","North America","North America","North America","Oceania","Africa","Asia","Europe","Africa","Africa","Asia","Europe","Europe","Oceania","Africa","Asia","Africa","Europe","Asia","Africa","South America","Europe","Europe","Asia","Asia","Asia","Africa","Asia","Asia","Africa","Oceania","North America","Africa","Asia","Asia","Oceania","Africa","Europe","Asia","Europe","North America","South America","Asia","Oceania","South America","Asia","Asia","Africa","Africa"],"Country":["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua & Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia and Herzegovina","Botswana","Brazil","British Virgin Islands","Brunei Darussalam","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Canada","Cape Verde","Central African Republic","Chad","Chile","China","Colombia","Comoros","Congo","Cook Islands","Costa Rica","Croatia","Cuba","Cyprus","Czechia","Democratic Republic of the Congo","Denmark","Djibouti","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea","Eritrea","Estonia","Ethiopia","Fiji","Finland","France","French Polynesia","Gabon","Gambia","Georgia","Germany","Ghana","Greece","Greenland","Grenada","Guatemala","Guinea","Guinea-Bissau","Guyana","Haiti","Honduras","Hong Kong","Hungary","Iceland","India","Indonesia","Iran","Iraq","Ireland","Israel","Italy","Jamaica","Japan","Jordan","Kazakhstan","Kenya","Kiribati","Kuwait","Kyrgyzstan","Lao People's Democratic Republic","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macao","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Marshall Islands","Mauritania","Mauritius","Mexico","Moldova","Mongolia","Montenegro","Morocco","Mozambique","Myanmar","Namibia","Nauru","Nepal","Netherlands","New Caledonia","New Zealand","Nicaragua","Niger","Nigeria","Niue","Democratic People's Republic of Korea","The former Yugoslav Republic of Macedonia","Norway","Oman","Pakistan","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal","Qatar","Romania","Russia","Rwanda","Saint Helena","Saint Kitts and Nevis","Saint Lucia","Saint Pierre and Miquelon","Saint Vincent and the Grenadines","Samoa","Sao Tome and Principe","Saudi Arabia","Serbia","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","Solomon Islands","Somalia","Republic of Korea","South Sudan","Spain","Sri Lanka","Sudan","Suriname","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor-Leste","Togo","Tonga","Trinidad and Tobago","Tunisia","Turkey","Turkmenistan","Tuvalu","Uganda","Ukraine","United Arab Emirates","United Kingdom","United States","Uruguay","Uzbekistan","Vanuatu","Venezuela","Vietnam","Yemen","Zambia","Zimbabwe"],"Emissions":["Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q5: 22.4 - 46","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q6: 46 - 208","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q5: 22.4 - 46","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q6: 46 - 208","Q2: 0.564 - 2.69","Q6: 46 - 208","Q6: 46 - 208","Q2: 0.564 - 2.69","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q2: 0.564 - 2.69","Q4: 7.8 - 22.4","Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q7: 208 - 9.96e+03","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q7: 208 - 9.96e+03","Q2: 0.564 - 2.69","Q1: 0.00765 - 0.564","Q2: 0.564 - 2.69","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q3: 2.69 - 7.8","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q3: 2.69 - 7.8","Q6: 46 - 208","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q1: 0.00765 - 0.564","Q5: 22.4 - 46","Q5: 22.4 - 46","Q7: 208 - 9.96e+03","Q3: 2.69 - 7.8","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q4: 7.8 - 22.4","Q4: 7.8 - 22.4","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q7: 208 - 9.96e+03","Q2: 0.564 - 2.69","Q3: 2.69 - 7.8","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q7: 208 - 9.96e+03","Q4: 7.8 - 22.4","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q1: 0.00765 - 0.564","Q2: 0.564 - 2.69","Q3: 2.69 - 7.8","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q6: 46 - 208","Q3: 2.69 - 7.8","Q7: 208 - 9.96e+03","Q7: 208 - 9.96e+03","Q7: 208 - 9.96e+03","Q7: 208 - 9.96e+03","Q5: 22.4 - 46","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q4: 7.8 - 22.4","Q7: 208 - 9.96e+03","Q5: 22.4 - 46","Q7: 208 - 9.96e+03","Q4: 7.8 - 22.4","Q1: 0.00765 - 0.564","Q6: 46 - 208","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q2: 0.564 - 2.69","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q4: 7.8 - 22.4","Q2: 0.564 - 2.69","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q7: 208 - 9.96e+03","Q2: 0.564 - 2.69","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q1: 0.00765 - 0.564","Q3: 2.69 - 7.8","Q3: 2.69 - 7.8","Q7: 208 - 9.96e+03","Q3: 2.69 - 7.8","Q6: 46 - 208","Q2: 0.564 - 2.69","Q6: 46 - 208","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q3: 2.69 - 7.8","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q6: 46 - 208","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q5: 22.4 - 46","Q3: 2.69 - 7.8","Q5: 22.4 - 46","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q4: 7.8 - 22.4","Q6: 46 - 208","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q6: 46 - 208","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q2: 0.564 - 2.69","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q2: 0.564 - 2.69","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q5: 22.4 - 46","Q4: 7.8 - 22.4","Q1: 0.00765 - 0.564","Q2: 0.564 - 2.69","Q7: 208 - 9.96e+03","Q2: 0.564 - 2.69","Q7: 208 - 9.96e+03","Q5: 22.4 - 46","Q5: 22.4 - 46","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q5: 22.4 - 46","Q5: 22.4 - 46","Q7: 208 - 9.96e+03","Q3: 2.69 - 7.8","Q4: 7.8 - 22.4","Q7: 208 - 9.96e+03","Q1: 0.00765 - 0.564","Q3: 2.69 - 7.8","Q1: 0.00765 - 0.564","Q5: 22.4 - 46","Q5: 22.4 - 46","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q3: 2.69 - 7.8","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q7: 208 - 9.96e+03","Q3: 2.69 - 7.8","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q4: 7.8 - 22.4"]},"z":null},"config":{"graphType":"Map","isR":true,"colorBy":"Emissions","topoJSON":"https://www.canvasxpress.org/data/maps/WORLD.json","mapId":"co2Quantile","colors":["#440154","#443983","#31688e","#21918c","#35b779","#90d743","#fde725","#d9dde3"],"mapColor":"#d9dde3","mapOutlineColor":"#ffffff","legendPosition":"bottom","legendColumns":4,"title":"CO2 emissions per country (2018)","subtitle":"Seven quantile classes computed in R: each colour holds about 28 of 198 countries"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>Every band of the ramp is doing work: the darkest purples are the smallest emitters, the yellows the largest, and the legend states each class’s actual value range — the edges are <em>data-driven</em>, not evenly spaced. The eighth colour, a neutral grey, catches map regions with no data so missing reads as missing. Hover any country for its name, continent, class and value.</p>
<p>If you prefer to keep the classing inside the engine, current CanvasXpress builds accept <code>colorSpectrum</code> (the ramp) plus <code>colorSpectrumBreaksMethod = "quantile"</code> and do the same cut at render time — the R route above works everywhere and keeps the breaks inspectable in your session.</p>
</section>
<section id="why-not-just-a-plain-linear-ramp" class="level2">
<h2 class="anchored" data-anchor-id="why-not-just-a-plain-linear-ramp">Why not just a plain linear ramp?</h2>
<p>Because the data is <strong>heavy-tailed</strong> — a few countries emit thousands of megatonnes while most emit almost nothing. On a linear scale, <strong>195 of these 198 countries fall into the bottom fifth of the range</strong>, so a continuous ramp paints nearly the whole world one pale tone and spends its colour on two or three outliers:</p>
<div class="cell">
<div class="sourceCode cell-code" id="cb10" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb10-1"><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">canvasXpress</span>(</span>
<span id="cb10-2">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">data      =</span> y,</span>
<span id="cb10-3">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">smpAnnot  =</span> x,</span>
<span id="cb10-4">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">graphType =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Map"</span>,</span>
<span id="cb10-5">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">colorBy   =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"CO2"</span>,</span>
<span id="cb10-6">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">topoJSON  =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://www.canvasxpress.org/data/maps/WORLD.json"</span>,</span>
<span id="cb10-7">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">mapId     =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"co2Linear"</span>,</span>
<span id="cb10-8">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">legendPosition =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"left"</span>,</span>
<span id="cb10-9">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">theme =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"solarized"</span>,</span>
<span id="cb10-10">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">title    =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"The same data on a plain linear ramp"</span>,</span>
<span id="cb10-11">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">subtitle =</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"195 of 198 countries sit in the bottom fifth of the scale - the map goes flat"</span>,</span>
<span id="cb10-12">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">width  =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">700</span>,</span>
<span id="cb10-13">  <span class="at" style="color: #657422;
background-color: null;
font-style: inherit;">height =</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">480</span></span>
<span id="cb10-14">)</span></code></pre></div>
<div class="cell-output-display">
<div id="htmlwidget-87196521e49fb3a0b9fd" style="width:100%;height:445px;" class="canvasXpress html-widget"></div>
<script type="application/json" data-for="htmlwidget-87196521e49fb3a0b9fd">{"x":{"data":{"y":{"vars":["CO2"],"smps":["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua & Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia and Herzegovina","Botswana","Brazil","British Virgin Islands","Brunei Darussalam","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Canada","Cape Verde","Central African Republic","Chad","Chile","China","Colombia","Comoros","Congo","Cook Islands","Costa Rica","Croatia","Cuba","Cyprus","Czechia","Democratic Republic of the Congo","Denmark","Djibouti","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea","Eritrea","Estonia","Ethiopia","Fiji","Finland","France","French Polynesia","Gabon","Gambia","Georgia","Germany","Ghana","Greece","Greenland","Grenada","Guatemala","Guinea","Guinea-Bissau","Guyana","Haiti","Honduras","Hong Kong","Hungary","Iceland","India","Indonesia","Iran","Iraq","Ireland","Israel","Italy","Jamaica","Japan","Jordan","Kazakhstan","Kenya","Kiribati","Kuwait","Kyrgyzstan","Lao People's Democratic Republic","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macao","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Marshall Islands","Mauritania","Mauritius","Mexico","Moldova","Mongolia","Montenegro","Morocco","Mozambique","Myanmar","Namibia","Nauru","Nepal","Netherlands","New Caledonia","New Zealand","Nicaragua","Niger","Nigeria","Niue","Democratic People's Republic of Korea","The former Yugoslav Republic of Macedonia","Norway","Oman","Pakistan","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal","Qatar","Romania","Russia","Rwanda","Saint Helena","Saint Kitts and Nevis","Saint Lucia","Saint Pierre and Miquelon","Saint Vincent and the Grenadines","Samoa","Sao Tome and Principe","Saudi Arabia","Serbia","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","Solomon Islands","Somalia","Republic of Korea","South Sudan","Spain","Sri Lanka","Sudan","Suriname","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor-Leste","Togo","Tonga","Trinidad and Tobago","Tunisia","Turkey","Turkmenistan","Tuvalu","Uganda","Ukraine","United Arab Emirates","United Kingdom","United States","Uruguay","Uzbekistan","Vanuatu","Venezuela","Vietnam","Yemen","Zambia","Zimbabwe"],"data":[[10.45,5.403,164.3,0.4642,37.68,0.1471,0.5056,185,6.297,0.9432,416,66.72,37.49,2.03,31.59,85.72,1.207,61.87,100.2,0.6122,7.76,0.6489,1.662,22.35,22.09,6.815,466.6,0.1736,9.56,43.55,4.14,0.568,15.48,7.567,586.5,0.6095,0.3005,1.008,85.83,9957,92.23,0.2459,3.518,0.07271,8.249,17.72,26.08,7.333,104.4,2.231,34.65,0.39,25.31,41.82,251.5,6.018,5.906,0.7088,17.71,16.18,2.124,45.85,331.7,0.7806,4.803,0.5632,9.862,755.4,14.48,71.8,0.5117,0.2786,19.41,3.032,0.3086,2.343,3.367,10.47,42.51,49.63,3.675,2591,576.6,755.4,211.3,38.8,62.21,348.1,8.01,1136,24.92,319.6,17.14,0.06888,104.2,10.17,32.26,7.859,27.57,2.426,1.274,45.21,0.1437,13.67,9.569,2.216,4.188,1.47,249.1,1.565,3.273,1.532,0.1531,3.935,4.902,451.1,5.878,64.51,2.123,65.37,8.383,26.1,4.154,0.04975,13.41,160.2,8.209,35.08,5.377,2.094,136.1,0.007653,38.16,6.981,43.82,71.03,247.4,12.1,6.786,8.103,54.21,138.9,337.7,51.48,109.2,76.95,1691,1.08,0.01132,0.249,0.3622,0.07923,0.2641,0.2679,0.1261,576.8,46.05,0.6054,0.9876,38.29,36.09,14.49,0.2985,0.6583,634.9,1.54,269.7,22.97,22.37,2.552,41.77,36.9,25.88,273.1,7.473,11.5,292.5,0.5204,3.167,0.1645,37.87,30.36,419.2,78.03,0.01148,5.385,231.7,188.5,380.1,5425,6.252,113.9,0.1454,129.6,211.8,9.945,6.93,11.34]]},"x":{"Code":["AFG","ALB","DZA","AND","AGO","AIA","ATG","ARG","ARM","ABW","AUS","AUT","AZE","BHS","BHR","BGD","BRB","BLR","BEL","BLZ","BEN","BMU","BTN","BOL","BIH","BWA","BRA","VGB","BRN","BGR","BFA","BDI","KHM","CMR","CAN","CPV","CAF","TCD","CHL","CHN","COL","COM","COG","COK","CRI","HRV","CUB","CYP","CZE","COD","DNK","DJI","DOM","ECU","EGY","SLV","GNQ","ERI","EST","ETH","FJI","FIN","FRA","PYF","GAB","GMB","GEO","DEU","GHA","GRC","GRL","GRD","GTM","GIN","GNB","GUY","HTI","HND","HKG","HUN","ISL","IND","IDN","IRN","IRQ","IRL","ISR","ITA","JAM","JPN","JOR","KAZ","KEN","KIR","KWT","KGZ","LAO","LVA","LBN","LSO","LBR","LBY","LIE","LTU","LUX","MAC","MDG","MWI","MYS","MDV","MLI","MLT","MHL","MRT","MUS","MEX","MDA","MNG","MNE","MAR","MOZ","MMR","NAM","NRU","NPL","NLD","NCL","NZL","NIC","NER","NGA","NIU","PRK","MKD","NOR","OMN","PAK","PAN","PNG","PRY","PER","PHL","POL","PRT","QAT","ROU","RUS","RWA","SHN","KNA","LCA","SPM","VCT","WSM","STP","SAU","SRB","SYC","SLE","SGP","SVK","SVN","SLB","SOM","KOR","SSD","ESP","LKA","SDN","SUR","SWE","CHE","SYR","TWN","TJK","TZA","THA","TLS","TGO","TON","TTO","TUN","TUR","TKM","TUV","UGA","UKR","ARE","GBR","USA","URY","UZB","VUT","VEN","VNM","YEM","ZMB","ZWE"],"Continent":["Asia","Europe","Africa","Europe","Africa","North America","North America","South America","Asia","North America","Oceania","Europe","Europe","North America","Asia","Asia","North America","Europe","Europe","North America","Africa","North America","Asia","South America","Europe","Africa","South America","North America","Asia","Europe","Africa","Africa","Asia","Africa","North America","Africa","Africa","Africa","South America","Asia","South America","Africa","Africa","Oceania","Central America","Europe","North America","Europe","Europe","Africa","Europe","Africa","North America","South America","Africa","Central America","Africa","Africa","Europe","Africa","Oceania","Europe","Europe","Oceania","Africa","Africa","Asia","Europe","Africa","Europe","North America","North America","Central America","Africa","Africa","South America","North America","Central America","Asia","Europe","Europe","Asia","Asia","Asia","Asia","Europe","Asia","Europe","North America","Asia","Asia","Asia","Africa","Oceania","Asia","Asia","Asia","Europe","Asia","Africa","Africa","Africa","Europe","Europe","Europe","Asia","Africa","Africa","Asia","Asia","Africa","Europe","Oceania","Africa","Africa","North America","Europe","Asia","Europe","Africa","Africa","Asia","Africa","Oceania","Asia","Europe","Oceania","Oceania","Central America","Africa","Africa","Oceania","Asia","Europe","Europe","Asia","Asia","Central America","Oceania","South America","South America","Asia","Europe","Europe","Africa","Europe","Asia","Africa","Africa","North America","North America","North America","North America","Oceania","Africa","Asia","Europe","Africa","Africa","Asia","Europe","Europe","Oceania","Africa","Asia","Africa","Europe","Asia","Africa","South America","Europe","Europe","Asia","Asia","Asia","Africa","Asia","Asia","Africa","Oceania","North America","Africa","Asia","Asia","Oceania","Africa","Europe","Asia","Europe","North America","South America","Asia","Oceania","South America","Asia","Asia","Africa","Africa"],"Country":["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua & Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia and Herzegovina","Botswana","Brazil","British Virgin Islands","Brunei Darussalam","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Canada","Cape Verde","Central African Republic","Chad","Chile","China","Colombia","Comoros","Congo","Cook Islands","Costa Rica","Croatia","Cuba","Cyprus","Czechia","Democratic Republic of the Congo","Denmark","Djibouti","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea","Eritrea","Estonia","Ethiopia","Fiji","Finland","France","French Polynesia","Gabon","Gambia","Georgia","Germany","Ghana","Greece","Greenland","Grenada","Guatemala","Guinea","Guinea-Bissau","Guyana","Haiti","Honduras","Hong Kong","Hungary","Iceland","India","Indonesia","Iran","Iraq","Ireland","Israel","Italy","Jamaica","Japan","Jordan","Kazakhstan","Kenya","Kiribati","Kuwait","Kyrgyzstan","Lao People's Democratic Republic","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macao","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Marshall Islands","Mauritania","Mauritius","Mexico","Moldova","Mongolia","Montenegro","Morocco","Mozambique","Myanmar","Namibia","Nauru","Nepal","Netherlands","New Caledonia","New Zealand","Nicaragua","Niger","Nigeria","Niue","Democratic People's Republic of Korea","The former Yugoslav Republic of Macedonia","Norway","Oman","Pakistan","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal","Qatar","Romania","Russia","Rwanda","Saint Helena","Saint Kitts and Nevis","Saint Lucia","Saint Pierre and Miquelon","Saint Vincent and the Grenadines","Samoa","Sao Tome and Principe","Saudi Arabia","Serbia","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","Solomon Islands","Somalia","Republic of Korea","South Sudan","Spain","Sri Lanka","Sudan","Suriname","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor-Leste","Togo","Tonga","Trinidad and Tobago","Tunisia","Turkey","Turkmenistan","Tuvalu","Uganda","Ukraine","United Arab Emirates","United Kingdom","United States","Uruguay","Uzbekistan","Vanuatu","Venezuela","Vietnam","Yemen","Zambia","Zimbabwe"],"Emissions":["Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q5: 22.4 - 46","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q6: 46 - 208","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q5: 22.4 - 46","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q6: 46 - 208","Q2: 0.564 - 2.69","Q6: 46 - 208","Q6: 46 - 208","Q2: 0.564 - 2.69","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q2: 0.564 - 2.69","Q4: 7.8 - 22.4","Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q7: 208 - 9.96e+03","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q7: 208 - 9.96e+03","Q2: 0.564 - 2.69","Q1: 0.00765 - 0.564","Q2: 0.564 - 2.69","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q3: 2.69 - 7.8","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q3: 2.69 - 7.8","Q6: 46 - 208","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q1: 0.00765 - 0.564","Q5: 22.4 - 46","Q5: 22.4 - 46","Q7: 208 - 9.96e+03","Q3: 2.69 - 7.8","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q4: 7.8 - 22.4","Q4: 7.8 - 22.4","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q7: 208 - 9.96e+03","Q2: 0.564 - 2.69","Q3: 2.69 - 7.8","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q7: 208 - 9.96e+03","Q4: 7.8 - 22.4","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q1: 0.00765 - 0.564","Q2: 0.564 - 2.69","Q3: 2.69 - 7.8","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q6: 46 - 208","Q3: 2.69 - 7.8","Q7: 208 - 9.96e+03","Q7: 208 - 9.96e+03","Q7: 208 - 9.96e+03","Q7: 208 - 9.96e+03","Q5: 22.4 - 46","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q4: 7.8 - 22.4","Q7: 208 - 9.96e+03","Q5: 22.4 - 46","Q7: 208 - 9.96e+03","Q4: 7.8 - 22.4","Q1: 0.00765 - 0.564","Q6: 46 - 208","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q2: 0.564 - 2.69","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q4: 7.8 - 22.4","Q2: 0.564 - 2.69","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q7: 208 - 9.96e+03","Q2: 0.564 - 2.69","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q1: 0.00765 - 0.564","Q3: 2.69 - 7.8","Q3: 2.69 - 7.8","Q7: 208 - 9.96e+03","Q3: 2.69 - 7.8","Q6: 46 - 208","Q2: 0.564 - 2.69","Q6: 46 - 208","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q3: 2.69 - 7.8","Q1: 0.00765 - 0.564","Q4: 7.8 - 22.4","Q6: 46 - 208","Q4: 7.8 - 22.4","Q5: 22.4 - 46","Q3: 2.69 - 7.8","Q2: 0.564 - 2.69","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q5: 22.4 - 46","Q3: 2.69 - 7.8","Q5: 22.4 - 46","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q4: 7.8 - 22.4","Q6: 46 - 208","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q6: 46 - 208","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q2: 0.564 - 2.69","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q1: 0.00765 - 0.564","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q2: 0.564 - 2.69","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q5: 22.4 - 46","Q4: 7.8 - 22.4","Q1: 0.00765 - 0.564","Q2: 0.564 - 2.69","Q7: 208 - 9.96e+03","Q2: 0.564 - 2.69","Q7: 208 - 9.96e+03","Q5: 22.4 - 46","Q5: 22.4 - 46","Q2: 0.564 - 2.69","Q5: 22.4 - 46","Q5: 22.4 - 46","Q5: 22.4 - 46","Q7: 208 - 9.96e+03","Q3: 2.69 - 7.8","Q4: 7.8 - 22.4","Q7: 208 - 9.96e+03","Q1: 0.00765 - 0.564","Q3: 2.69 - 7.8","Q1: 0.00765 - 0.564","Q5: 22.4 - 46","Q5: 22.4 - 46","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q3: 2.69 - 7.8","Q7: 208 - 9.96e+03","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q7: 208 - 9.96e+03","Q3: 2.69 - 7.8","Q6: 46 - 208","Q1: 0.00765 - 0.564","Q6: 46 - 208","Q7: 208 - 9.96e+03","Q4: 7.8 - 22.4","Q3: 2.69 - 7.8","Q4: 7.8 - 22.4"]},"z":null},"config":{"graphType":"Map","isR":true,"colorBy":"CO2","topoJSON":"https://www.canvasxpress.org/data/maps/WORLD.json","mapId":"co2Linear","legendPosition":"left","theme":"solarized","title":"The same data on a plain linear ramp","subtitle":"195 of 198 countries sit in the bottom fifth of the scale - the map goes flat"},"events":null,"afterRender":null},"evals":[],"jsHooks":[]}</script>
</div>
</div>
<p>This is the single most common choropleth failure. The cure is <strong>classing</strong>:</p>
<ul>
<li><code>colorSpectrumBreaksMethod = "quantile"</code> — equal <em>counts</em> per class. Every colour is used, by construction. The right default for skewed data and for “which regions rank high/low” questions.</li>
<li><code>colorSpectrumBreaksMethod = "jenks"</code> — natural breaks that minimise within-class variance. Best when the data has genuine clusters with gaps between them; on smoothly heavy-tailed data like this it piles almost everything into the bottom class, so check the legend before you trust it.</li>
<li>Three to seven classes is the usable range — beyond that, readers cannot match colours to the legend.</li>
</ul>
</section>
<section id="choose-the-palette-on-purpose" class="level2">
<h2 class="anchored" data-anchor-id="choose-the-palette-on-purpose">Choose the palette on purpose</h2>
<p>The palette is not decoration — it is the scale’s grammar:</p>
<ul>
<li><p><strong>Sequential</strong> (dark → light of ordered hues, like viridis above) for a quantity that only goes up: counts, rates, concentrations.</p></li>
<li><p><strong>Diverging</strong> (two hues meeting at a neutral midpoint) when values are meaningful <em>above and below a reference</em>: change vs.&nbsp;last year, difference from a target, a signed index. Give canvasXpress a three-colour <code>colorSpectrum</code> and pin the midpoint with <code>colorSpectrumZeroValue</code>:</p>
<div class="sourceCode" id="cb11" style="background: #f1f3f5;"><pre class="sourceCode r code-with-copy"><code class="sourceCode r"><span id="cb11-1">colorBy <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Change"</span>,</span>
<span id="cb11-2">colorSpectrum <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">list</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#2166ac"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#f7f7f7"</span>, <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"#b2182b"</span>),  <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># blue - neutral - red</span></span>
<span id="cb11-3">colorSpectrumZeroValue <span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">0</span>                               <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;"># value mapped to the middle colour</span></span></code></pre></div>
<p>Never use a diverging palette for a purely positive quantity — the neutral midpoint invents a “normal” that the data does not have.</p></li>
</ul>
<p>Viridis and the ColorBrewer ramps are colour-blind-safe and perceptually ordered; a rainbow ramp is neither, so readers cannot tell which end means “more”. Keep the <em>same</em> scale across small multiples so maps stay comparable.</p>
</section>
<section id="polish-legend-labels-and-base-styling" class="level2">
<h2 class="anchored" data-anchor-id="polish-legend-labels-and-base-styling">Polish: legend, labels and base styling</h2>
<ul>
<li><code>subtitle</code> / <code>source</code> — caption the units and provenance.</li>
<li><code>legendNumberFormat = list(style = "decimal", decimals = 1, suffix = "%")</code> — format the legend ticks as percentages, currency, etc.</li>
<li><code>mapColor</code> / <code>mapOutlineColor</code> — the fill for regions with <strong>no data</strong> (a neutral grey) and the border between shapes, so missing data reads as missing rather than as a value.</li>
<li><code>showMapLabels = TRUE</code> — draw region names (best on maps with few regions, e.g.&nbsp;a single country’s provinces; it clutters a 190-country world map).</li>
<li><code>legendInside = TRUE</code> — float the legend over empty ocean to reclaim width.</li>
</ul>
</section>
<section id="beyond-the-world-map" class="level2">
<h2 class="anchored" data-anchor-id="beyond-the-world-map">Beyond the world map</h2>
<ul>
<li><strong>Other boundaries.</strong> Point <code>topoJSON</code> at any shape file — US states, a single country’s regions, counties, custom districts. The join key is just the shape name.</li>
<li><strong>Projection.</strong> <code>mapProjection = "albers"</code> (equal-area, good for the US) or <code>"mercator"</code>. Equal-area projections matter for choropleths: Mercator inflates high latitudes, exaggerating those regions’ visual weight.</li>
<li><strong>Categorical maps.</strong> Point <code>colorBy</code> at a categorical column (an election winner, a priority tier) for a qualitative choropleth with a discrete legend.</li>
<li><strong>Markers.</strong> Add <code>decorations</code> to drop labelled points on cities or call out specific regions.</li>
</ul>
<p>The whole figure — data, boundaries, classing rule and palette — travels together as one spec, so a reviewer can reproduce it exactly and a colleague can re-render it from Python or JavaScript.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../choropleth-maps-in-python/">Choropleth maps in Python</a></li>
<li><a href="../choropleth-maps-in-javascript/">Choropleth maps in JavaScript</a></li>
<li><a href="../clustered-heatmap-in-r/">Clustered heatmaps in R</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
</ul>


</section>

 ]]></description>
  <category>R</category>
  <category>canvasXpress</category>
  <category>maps</category>
  <category>choropleth</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/r/choropleth-maps-in-r/</guid>
  <pubDate>Tue, 06 Oct 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/r/choropleth-maps-in-r/thumbnail.png" medium="image" type="image/png" height="112" width="144"/>
</item>
<item>
  <title>Sankey / alluvial diagrams in JavaScript with CanvasXpress</title>
  <dc:creator>Isaac Neuhaus</dc:creator>
  <link>https://neuhausi.github.io/canvasxpress-blog/posts/js/sankey-diagrams-in-javascript/</link>
  <description><![CDATA[ 




<p>A Sankey (or alluvial) diagram shows how a quantity <strong>flows through a sequence of categorical stages</strong> — patients moving from a cohort, to a treatment, to an outcome. The width of each stream is the magnitude. CanvasXpress is a JavaScript library at heart, so in the browser it’s just a <code>data</code> object and a <code>config</code>.</p>
<section id="load-the-library" class="level2">
<h2 class="anchored" data-anchor-id="load-the-library">Load the library</h2>
<div class="sourceCode" id="cb1" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb1-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">link</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> href</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@69.6.1/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> rel</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"stylesheet"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb1-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> src</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@69.6.1/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="the-markup-and-the-spec" class="level2">
<h2 class="anchored" data-anchor-id="the-markup-and-the-spec">The markup and the spec</h2>
<p>Each row is one path through the stages; the value (<code>Freq</code>) is the single variable, and the stages are sample annotations (<code>x</code>). <code>sankeyAxes</code> lists the stages in order.</p>
<div class="sourceCode" id="cb2" style="background: #f1f3f5;"><pre class="sourceCode html code-with-copy"><code class="sourceCode html"><span id="cb2-1"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> id</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sankey"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> width</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"700"</span><span class="ot" style="color: #003B4F;
background-color: null;
font-style: inherit;"> height</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span><span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"500"</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">canvas</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-2"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span>
<span id="cb2-3">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> cohorts <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cohort A"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cohort B"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-4">      treats  <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Drug 1"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Drug 2"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Placebo"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-5">      outcomes <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Response"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Stable"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Progression"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-6"></span>
<span id="cb2-7">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> Cohort <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> Treatment <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> Outcome <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> Freq <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> []<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-8">  cohorts<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">forEach</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (co) {</span>
<span id="cb2-9">    treats<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">forEach</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (tr) {</span>
<span id="cb2-10">      outcomes<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">forEach</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (ou) {</span>
<span id="cb2-11">        <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> base <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> ou <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">===</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Response"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">?</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">40</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> ou <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">===</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Stable"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">?</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">25</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">15</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-12">        <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">if</span> (tr <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">===</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Placebo"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">&amp;&amp;</span> ou <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">===</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Response"</span>) base <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">12</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span>   <span class="co" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">// placebo responds less</span></span>
<span id="cb2-13">        Cohort<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(co)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> Treatment<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(tr)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> Outcome<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(ou)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-14">        Freq<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">push</span>(base <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">floor</span>(<span class="bu" style="color: null;
background-color: null;
font-style: inherit;">Math</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">random</span>() <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">*</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">16</span>))<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-15">      })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-16">    })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-17">  })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-18"></span>
<span id="cb2-19">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> ids <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> Freq<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">.</span><span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">map</span>(<span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">function</span> (_<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> i) { <span class="cf" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">return</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"r"</span> <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> (i <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">+</span> <span class="dv" style="color: #AD0000;
background-color: null;
font-style: inherit;">1</span>)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span> })<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-20"></span>
<span id="cb2-21">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> data <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb2-22">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">y</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">vars</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Freq"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">smps</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> ids<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">data</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [Freq] }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-23">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">x</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> { <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Cohort</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> Cohort<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Treatment</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> Treatment<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">Outcome</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> Outcome }</span>
<span id="cb2-24">  }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-25"></span>
<span id="cb2-26">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">var</span> config <span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">=</span> {</span>
<span id="cb2-27">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Sankey"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-28">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">sankeyAxes</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Cohort"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Treatment"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Outcome"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-29">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">xAxis</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> [<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Freq"</span>]<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-30">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">colorBy</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Outcome"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-31">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">sankeyType</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"proportional"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-32">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">graphOrientation</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"horizontal"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span></span>
<span id="cb2-33">    <span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">title</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">:</span> <span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"Patient flow: cohort to treatment to outcome"</span></span>
<span id="cb2-34">  }<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-35"></span>
<span id="cb2-36">  <span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">new</span> <span class="fu" style="color: #4758AB;
background-color: null;
font-style: inherit;">CanvasXpress</span>(<span class="st" style="color: #20794D;
background-color: null;
font-style: inherit;">"sankey"</span><span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> data<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">,</span> config)<span class="op" style="color: #5E5E5E;
background-color: null;
font-style: inherit;">;</span></span>
<span id="cb2-37"><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&lt;/</span><span class="kw" style="color: #003B4F;
background-color: null;
font-weight: bold;
font-style: inherit;">script</span><span class="dt" style="color: #AD0000;
background-color: null;
font-style: inherit;">&gt;</span></span></code></pre></div>
</section>
<section id="live-result" class="level2">
<h2 class="anchored" data-anchor-id="live-result">Live result</h2>
<link href="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@69.6.1/inst/htmlwidgets/lib/canvasXpress/canvasXpress.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/gh/neuhausi/canvasXpress@69.6.1/inst/htmlwidgets/lib/canvasXpress/canvasXpress.min.js"></script>
<canvas id="sankeyLive" width="700" height="500"></canvas>
<script>
(function () {
  function draw() {
    if (typeof CanvasXpress === "undefined") { return setTimeout(draw, 60); }
    var cohorts = ["Cohort A", "Cohort B"], treats = ["Drug 1", "Drug 2", "Placebo"],
        outcomes = ["Response", "Stable", "Progression"];
    var Cohort = [], Treatment = [], Outcome = [], Freq = [];
    cohorts.forEach(function (co) {
      treats.forEach(function (tr) {
        outcomes.forEach(function (ou) {
          var base = ou === "Response" ? 40 : ou === "Stable" ? 25 : 15;
          if (tr === "Placebo" && ou === "Response") base = 12;
          Cohort.push(co); Treatment.push(tr); Outcome.push(ou);
          Freq.push(base + Math.floor(Math.random() * 16));
        });
      });
    });
    var ids = Freq.map(function (_, i) { return "r" + (i + 1); });
    new CanvasXpress("sankeyLive",
      { y: { vars: ["Freq"], smps: ids, data: [Freq] },
        x: { Cohort: Cohort, Treatment: Treatment, Outcome: Outcome } },
      { graphType: "Sankey", sankeyAxes: ["Cohort", "Treatment", "Outcome"], xAxis: ["Freq"],
        colorBy: "Outcome", sankeyType: "proportional", graphOrientation: "horizontal",
        title: "Patient flow: cohort to treatment to outcome" });
  }
  draw();
})();
</script>
<p>Hover any stream to see the count; the widths are proportional to the frequency. <code>sankeyType</code> can also be <code>"aligned"</code> (classic alluvial) or <code>"equal"</code>.</p>
</section>
<section id="why-reproducible" class="level2">
<h2 class="anchored" data-anchor-id="why-reproducible">Why “reproducible”</h2>
<p>The <code>data</code>+<code>config</code> <strong>is</strong> the figure — one portable JSON spec that renders the same from R, Python, or a web page.</p>
</section>
<section id="next" class="level2">
<h2 class="anchored" data-anchor-id="next">Next</h2>
<ul>
<li><a href="../volcano-plots-in-javascript/">Interactive volcano plots in JavaScript</a></li>
<li>Gallery: <a href="https://canvasxpress.org/examples.html" class="uri">https://canvasxpress.org/examples.html</a></li>
<li>Source &amp; npm: <a href="https://github.com/neuhausi/canvasXpress" class="uri">https://github.com/neuhausi/canvasXpress</a></li>
</ul>


</section>

 ]]></description>
  <category>JavaScript</category>
  <category>CanvasXpress</category>
  <category>sankey</category>
  <category>visualization</category>
  <guid>https://neuhausi.github.io/canvasxpress-blog/posts/js/sankey-diagrams-in-javascript/</guid>
  <pubDate>Mon, 28 Sep 2026 04:00:00 GMT</pubDate>
  <media:content url="https://neuhausi.github.io/canvasxpress-blog/posts/js/sankey-diagrams-in-javascript/thumbnail.png" medium="image" type="image/png" height="108" width="144"/>
</item>
</channel>
</rss>
