UNPKG

ideogram

Version:

Chromosome visualization for the web

129 lines (103 loc) 3.58 kB
/** * @fileoverview Functions for 2D heatmaps of genome annotations. * 2D heatmaps enable showing many (100+) tracks of data in one dimension, * for features (e.g. genes) along a dimension of genomic coordinates in * chromosome context. * * TO DO: * - Horizontal orientation * - Multiple chromosomes * - Non-human organisms */ import {d3} from '../lib'; import {getHeatmapAnnotColor} from './heatmap-lib'; /** * Add one canvas that will contain all annotations. One canvas per chromosome. */ function writeCanvas(chr, ideoHeight, width, ideo) { var left, canvas, context, id; id = chr.id + '-canvas'; // e.g. chr1-9606-canvas left = (ideo.config.chrWidth * 2) + ideo.config.annotationHeight - 0.5; canvas = d3.select(ideo.config.container + ' #_ideogramInnerWrap') .append('canvas') .attr('id', id) .attr('width', width) .attr('height', ideoHeight) .style('position', 'absolute') .style('left', left + 'px') .style('top', '0px'); context = canvas.nodes()[0].getContext('2d'); return context; } /** * Render annotations on the canvas. * * These annotations are 2D; each annotation has many values, each on a track. */ function fillCanvasAnnotValues(annot, context, ideo) { var i, x, values, annotHeight = ideo.config.annotationHeight, ideoMarginTop = ideo._layout.margin.top; values = annot.values; // Fill canvas with annotation colors to draw the heatmap for (i = 0; i < values.length; i++) { context.fillStyle = values[i]; x = (i - 1) * annotHeight; context.fillRect(x, annot.startPx + ideoMarginTop, annotHeight, 2); } } /** * Draw a 2D heatmap of annotations along one chromosome. * * TODO: * - Support in 'horizontal' orientation * - Support after rotating chromosome on click */ function drawHeatmaps2d(annotContainers, ideo) { var annot, context, i, chr, container = ideo.config.container, ideoMarginTop = ideo._layout.margin.top, ideoHeight = ideo.config.chrHeight + ideoMarginTop, width = ideo.config.annotationHeight * annotContainers[0].values.length; d3.selectAll(container + ' canvas').remove(); d3.select(container + ' #_ideogramInnerWrap') .style('max-width', width + 'px'); d3.select(container + ' #_ideogram').attr('width', width); chr = ideo.chromosomesArray[0]; context = writeCanvas(chr, ideoHeight, width, ideo); // Each "annotationContainer" represents annotations for a chromosome for (i = 0; i < annotContainers.length; i++) { annot = annotContainers[i]; fillCanvasAnnotValues(annot, context, ideo); } if (ideo.onDrawAnnotsCallback) { ideo.onDrawAnnotsCallback(); } } function add2dAnnotsForChr(annots, omittedAnnots, annotsByChr, chrModel, m, keys, ideo) { var j, k, annot, ra, stop, stopPx, color, thresholds = ideo.config.heatmapThresholds; for (j = 0; j < annotsByChr.annots.length; j++) { ra = annotsByChr.annots[j]; annot = {}; annot.values = []; // one value per track for (k = 0; k < 3; k++) { annot[keys[k]] = ra[k]; } for (k = 3; k < keys.length; k++) { color = getHeatmapAnnotColor(thresholds, ra[k]); annot.values.push(color); } stop = annot.start + annot.length; annot.chr = annotsByChr.chr; annot.chrIndex = m; annot.startPx = ideo.convertBpToPx(chrModel, annot.start); stopPx = ideo.convertBpToPx(chrModel, stop); annot.px = Math.round((annot.startPx + stopPx) / 2); annots.push(annot); } annots.shift(); return [annots, omittedAnnots]; } export {drawHeatmaps2d, add2dAnnotsForChr};