UNPKG

ideogram

Version:

Chromosome visualization for the web

181 lines (141 loc) 4.98 kB
import {d3} from '../lib'; import {initTools} from '../tools/tools'; import {ModelAdapter} from '../model-adapter'; import {Chromosome} from './chromosome'; /** * Adds a copy of a chromosome (i.e. a homologous chromosome, homolog) to DOM * * @param chrModel * @param chrIndex * @param homologIndex * @param container */ function appendHomolog(chrModel, chrIndex, homologIndex, container) { var homologOffset, chromosome, shape, defs, adapter; defs = d3.select(this.selector + ' defs'); // Get chromosome model adapter class adapter = ModelAdapter.getInstance(chrModel); // How far this copy of the chromosome is from another homologOffset = homologIndex * this.config.chrMargin; // Append chromosome's container chromosome = container .append('g') .attr('id', chrModel.id) .attr('class', 'chromosome ' + adapter.getCssClass()) .attr('transform', 'translate(0, ' + homologOffset + ')'); // Render chromosome shape = Chromosome.getInstance(adapter, this.config, this) .render(chromosome, chrIndex, homologIndex); d3.select('#' + chrModel.id + '-chromosome-set-clippath').remove(); defs.append('clipPath') .attr('id', chrModel.id + '-chromosome-set-clippath') .selectAll('path') .data(shape) .enter() .append('path') .attr('d', function(d) {return d.path;}) .attr('class', function(d) {return d.class;}); if (chrModel.width < 1) { d3.select('#' + chrModel.id + ' .bands').style('opacity', 0); } } /** * Renders all the bands and outlining boundaries of a chromosome. */ function drawChromosome(chrModel) { var chrIndex, container, numChrsInSet, transform, homologIndex, chrSetSelector; chrIndex = chrModel.chrIndex; transform = this._layout.getChromosomeSetTranslate(chrIndex); chrSetSelector = this.selector + ' #' + chrModel.id + '-chromosome-set'; d3.selectAll(chrSetSelector + ' g').remove(); container = d3.select(chrSetSelector); if (container.nodes().length === 0) { // Append chromosome set container container = d3.select(this.selector) .append('g') .attr('class', 'chromosome-set') .attr('transform', transform) .attr('id', chrModel.id + '-chromosome-set'); } if ( 'sex' in this.config && this.config.ploidy === 2 && this.sexChromosomes.index === chrIndex ) { this.drawSexChromosomes(container, chrIndex); return; } numChrsInSet = 1; if (this.config.ploidy > 1) { numChrsInSet = this._ploidy.getChromosomesNumber(chrIndex); } for (homologIndex = 0; homologIndex < numChrsInSet; homologIndex++) { this.appendHomolog(chrModel, chrIndex, homologIndex, container); } } /** * Rotates a chromosome 90 degrees and shows or hides all other chromosomes * Useful for focusing or defocusing a particular chromosome */ function rotateAndToggleDisplay(chrElement) { var chrName, chrModel, chrIndex; this.unhighlight(); // Do nothing if taxid not defined. But it should be defined. // To fix that bug we should have a way to find chromosome set number. if (!this.config.taxid) return; chrName = chrElement.id.split('-')[0].replace('chr', ''); chrModel = this.chromosomes[this.config.taxid][chrName]; chrIndex = chrModel.chrIndex; this._layout.rotate(chrIndex, chrIndex, chrElement); } function setOverflowScroll() { var ideo, config, ideoWidth, ideoInnerWrap, ideoMiddleWrap, ideoSvg, ploidy, ploidyPad; ideo = this; config = ideo.config; ideoSvg = d3.select(config.container + ' svg#_ideogram'); ideoInnerWrap = d3.select(config.container + ' #_ideogramInnerWrap'); ideoMiddleWrap = d3.select(config.container + ' #_ideogramMiddleWrap'); ploidy = config.ploidy; if (ploidy === 1) { ploidyPad = ploidy; } else { ploidyPad = ploidy * 1.12; } let annotHeight = 0; if ('annotationsLayout' in config) { annotHeight = config.annotationHeight * config.numAnnotTracks; } if ( config.orientation === 'vertical' && config.perspective !== 'comparative' && config.geometry !== 'collinear' ) { ideoWidth = (ideo.numChromosomes) * (config.chrWidth + config.chrMargin + annotHeight); } else { return; } if (config.annotationsLayout === 'heatmap-2d') { return; } ideoWidth = Math.ceil(ideoWidth * ploidyPad / config.rows); if (ideo._layout._class === 'SmallLayout') ideoWidth += 100; ideoWidth += 35; // Account for settings gear // Ensures absolutely-positioned elements, e.g. heatmap overlaps, display // properly if ideogram container also has position: absolute ideoMiddleWrap.style('height', ideo._layout.getHeight() + 'px'); ideoInnerWrap .style('max-width', ideoWidth + 'px') .style('overflow-x', 'scroll') .style('position', 'absolute'); ideoSvg.style('min-width', (ideoWidth - 5) + 'px'); if (ideo.config.showTools) { initTools(ideo); } } export { appendHomolog, drawChromosome, rotateAndToggleDisplay, setOverflowScroll };