A very simple example

To demonstrate how easy it is to create interactive data exploration apps with linked-charts, we show here a very simple example, complete with the code needed to create it.

This example visualizes an excerpt of data from a project within FIMM's Individualized Systems Medicine programme. From a cohort of (here) 52 patients with acute myeloid leukaemia (AML), samples of tumour cells were acquired by means of bone marrow aspiration. Each sample was assayed by various means, including RNA-Seq to measure gene expressions and an assay which tested the sensitivity of each sample to a large panel of drugs. For the latter, aliqots of the samples were incubated with the drugs and then viability was measured.

For this example, we ask the simple question: Which drugs correlate with which genes?

For illustration purposes, the data was preselected to 10 drugs (all topoisomerase inhibitors) and 35 genes. For each pair of a drug and a gene, the heat map visualizes the Pearson correlation between the sensitivity of the drug and the expression of the gene over all samples.

A correlation coefficient is merely a summary statistic. It is valuable to be able to inspect the underlying data. Here, a click on a heat map cells shows this underlying data in a scatter plot; expression of the selected gene on the x axis, sensitivity to the selected drug on the y axis, each point representing one sample.

This linking of a chart visualizing a summary statistic with a chart drilling down into the data of a specific data element is a prototypical use case of linked-charts.

The code for the example

A user of our framework can create apps with very little code. Bellow we show the part of the code that hasn't been explained in previous examples. You can find the complete code at the bottom of the page.

<script src="linked-charts.min.js"></script> 
<link rel="stylesheet" type="text/css" href="linked-charts.css"> 

<script>
  geneNames = [ "CD248", "CA6", ... , "PDGFB" ]
  geneExprs = [ [ 4.3119, 3.1594, ... , 3.516] , [ ... ], ... ]
  drugNames = [ "Irinotecan", "Topotecan", ..., "Valrubicin" ]
  drugScores = [ [ 3.2, 0.1, 0, 4.6, ... ], [ ... ], ... ]
</script>

<table><tr>
  <td id="heatmap" valign="top"></td>
  <td id="scatterplot" valign="top"></td>
</tr></table>

<script>

var selGene = 0;
var selDrug = 0;

var scatterplot = lc.scatter()
  .x( function( k ) { return geneExprs[selGene][k] } )
  .y( function( k ) { return drugScores[selDrug][k] } )
  .place("#scatterplot");

var heatmap = lc.heatmap()
  .nrows( geneNames.length )
  .ncols( drugNames.length )
  .height( 650 )
  .width( 400 )
  .colourDomain( [ -1, 1 ] )
  .palette( d3.interpolateRdBu )
  .value( function( row, col ) {
     return lc.pearsonCorr( geneExprs[row], drugScores[col] )
   } )
  .rowLabel( function(row) {
     return geneNames[row]
   } )
  .colLabel( function(col) {
     return drugNames[col]
   } )
  .on_click( function( rowId, colId ) {
     selGene = rowId;
     selDrug = colId;
     scatterplot.update();
  })
  .place( "#heatmap")
</script>

Click on all the yellow bubbles (), going from top to bottom, to see explanations of the code.


Here we load the linked-charts library and its stylesheet. It comes bundled with d3, d3-beeswarm plugin and FileSaver.js

There are various ways to load the data. Here, we demonstrate the simplest way: just inline it into the page.

The data was originally an R matrix. We used the toJSON function of R's 'jsonlite' package to write out the data in a form that can be read in JavaScript, and copied and pasted this here.

More about data input you can find here

The labels for the heatmap will be taken from these two string vectors. The vectors have lengths 35 and 10, but some of the elements have been omitted to not clutter the page.
The main data are given in these two data matrices. The first contains 35 × 52 gene expression values for 35 genes (matrix rows) times 52 samples (matrix columns). The second contains drug response scores for 10 drugs times the same 52 samples.
The layout of a set of linked charts is specified by writing a normal web page in standard HTML. Here, our page merely contains one table with one row and two table data (<td>) elements, each of which will take up one of the charts. Further below, we will refer to these <td> by the id attributes that are set here.
This is the actual user script to use the linked-charts library.

These two global variables provide the link between the heatmap and the scatter plot:

They always show the row number (gene) and column number (drug) of the last heatmap cell on which the user has clicked (or, initially, 0, i.e., the top-left cell).

Here, we initialize a scatter object. This is one of the standard chart types provided by our linked-charts library.

In the following lines, we set the object's properties

Linked-charts uses call-back functions to access the data: These two functions are called for each data point, being passed the number of the data point as argument. They look up the gene expression and drug response score in the input matrices, looking at the column for sample k.

The global variables defined above are consulted, so that the scatter plot uses the data from the rows corresponding to gene and drug selected by the user's last click on the heatmap.

Axes and scaling is automatically adjusted to the value range (but this can be overridden).

Besides x and y coordinates, other properties of the data points such as colour, size etc, can be set similarly, either globally for all points by providing constants, or for each point separately.

The place function inserts the object into the web page. The argument is a CSS selector, here selecting the table elements that were marked with id attributes as the places to take up the charts.

Here, we instantiate the second chart, namely the heatmap on the left. The heatmap is another of the standard chart types provided by the linked-charts library.

Here, we set the basic properties of the heatmap: The numbers of rows (nrows) and columns (ncols), and the height and width (in pixels).

The number of rows (number of genes) and columns (number of drugs) is read off from the number of rows of the two data arrays.

We use one of D3's color palettes for the heatmap's colour scale. These colours should map the correlation values, which range from -1 to 1.

As do all charts in the linked-charts library, heatmaps access their data via callback functions. For this, the property value has to be set to a function that takes two arguments, rowId and colId and returns the value that the cell with the given position should show.

Here, we provide a function that looks up the data row corresponding to rowId in the geneExpr matrix and the data row corresponding to colId in the drugScore matrix. It then calculates for these two row vectors Pearson's correlation coefficient and returns it.

This example shows that it is not necessary to bring the data into a specific form to display it with linked-charts. Thanks to the call-back mechanism, we can code access to the data in whatever form it is provided and even do small calculations on the fly.

The row and column labels displayed at the side of the heatmap are also provided by call-back functions, which are called individually for each row and each column.

In our input data, the mapping of rows of the input data matrices to gene and drug names is provided by two vectors of labels, which are accessed here.

The property on_click is set here to a call back function that is called whenever the user clicks on a cell.

The function takes the row and column index of the clicked heatmap cell from the provided arguments and saves them in the two global variables selGene and selDrug that we have defined at the top and which are read by the scatter plot's x and y call-backs.

Then, the update function of the scatter chart is called. This has to be done whenever the data or appearance of a plot changed and the plot has to be re-rendered.

This simple and transparent style of linking two plots is the heart of linked-charts.

Show/hide full code