Skip to content

Instantly share code, notes, and snippets.

@park-brian
Last active July 6, 2021 15:39
Show Gist options
  • Save park-brian/b20851ceb107c4e26f8767987914bff9 to your computer and use it in GitHub Desktop.
Save park-brian/b20851ceb107c4e26f8767987914bff9 to your computer and use it in GitHub Desktop.
Breast Cancer QQ Plot
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>GistRun</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>PLCO QQ Plot</h1>
<div id="qq-plot" style="width: 100%; height: 600px; position: relative;"></div>
<script src="https://cdn.plot.ly/plotly-2.1.0.min.js"></script>
<script src="script.js"></script>
</body>
</html>
(async function main() {
const plotContainer = document.getElementById('qq-plot');
// breast cancer
const params = {
phenotype_id: 3080,
sex: 'female',
ancestry: 'european'
};
// retrieve qq plot points
const points = await queryPLCO('points', params);
// retrieve metadata (use chromosome: 'all' to retrieve only summary metadata for all chromosomes)
const metadata = await queryPLCO('metadata', {...params, chromosome: 'all'});
const lambdaGC = metadata[0].lambda_gc;
const count = metadata[0].count;
// transform data to traces
const data = [
{
x: points.data.map(e => e.p_value_nlog_expected),
y: points.data.map(e => e.p_value_nlog),
customdata: points.data.map(e => ({
...params,
id: e.id
})),
mode: 'markers',
type: 'scattergl',
hoverinfo: 'none',
}
];
// set layout
const layout = {
title: `Breast Cancer <br>lambdaGC: ${lambdaGC} <br>variants: ${count}`,
xaxis: {
title: 'Expected -log<sub>10</sub>p'
},
yaxis: {
title: 'Observed -log<sub>10</sub>p'
}
}
// draw qq plot
Plotly.newPlot(plotContainer, data, layout);
// create tooltip
const tooltip = createTooltip();
tooltip.setClass('tooltip');
plotContainer.appendChild(tooltip.ref);
// on hover, retrieve and show variant details in tooltip
plotContainer.on('plotly_unhover', tooltip.hide);
plotContainer.on('plotly_hover', async event => {
if (!event.points || !event.points.length) return;
const point = event.points[0];
tooltip.hide();
// retrieve variant
const params = point.data.customdata[point.pointIndex];
const variants = await queryPLCO('variants', params);
const variant = variants.data[0];
// show tooltip for variant
tooltip.setPosition(point);
tooltip.setContent(JSON.stringify(variant, null, 2));
tooltip.show();
});
})();
// Utility Functions
function queryPLCO(resource, params = {}, apiRoot = 'https://exploregwas.cancer.gov/plco-atlas/api/') {
return fetch(apiRoot + resource + asQueryString(params)).then(response => response.json());
}
function asQueryString(params = {}) {
return '?' + Object.entries(params)
.map(([key, value]) => [key, value].map(encodeURIComponent).join('='))
.join('&');
}
function createTooltip() {
var div = document.createElement('div');
div.style.position = 'absolute';
div.style.display = 'none';
return {
setClass: className => div.className = className,
setContent: html => div.innerHTML = html,
setPosition: point => {
const { xaxis, yaxis } = point;
const x = point.data.x[point.pointIndex];
const y = point.data.y[point.pointIndex];
const screenX = xaxis.l2p(x) + xaxis._offset;
const screenY = yaxis.l2p(y) + yaxis._offset;
div.style.left = `${screenX}px`;
div.style.top = `${screenY}px`;
},
hide: () => div.style.display = 'none',
show: () => div.style.display = 'inline-block',
ref: div,
};
}
body {
font-family: sans-serif;
}
.tooltip {
background-color: white;
padding: 0.5rem;
border-radius: 4px;
box-shadow: 0 4px 4px #ddd;
white-space: pre;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment