in client/client/modules/render/variant-render/renderers/structural-variant-renderer.js [104:358]
_manageReferenceViewports(config) {
this._breakpointPositioning.clear();
if (!this._transcriptExpandedStatus) {
this._transcriptExpandedStatus = {};
}
let maximumItemsLength = 0;
let maximumLeftLength = 0;
let maximumRightLength = 0;
let maximumBreakpointsPerChromosome = 0;
const chromosomeVisualInfo = {};
const refZone = {name: 'reference', zones: []};
let maxChromosomeLabelSize = 0;
const geneTranscriptsZones = [];
for (let i = 0; i < this.variant.analysisResult.chromosomes.length; i++) {
const name = this._getChromosomeDisplayName(this.variant.analysisResult.chromosomes[i]);
const size = PixiTextSize.getTextSize(name, this.config.chromosome.label);
if (maxChromosomeLabelSize < size.width) {
maxChromosomeLabelSize = size.width;
}
}
for (let i = 0; i < this.variant.analysisResult.chromosomes.length; i++) {
const subZone = {
name: this.variant.analysisResult.chromosomes[i].toUpperCase(),
zones: []
};
refZone.zones.push(subZone);
const breakpointsAtChromosome = this.variant.analysisResult.breakpoints.filter(breakpoint => breakpoint.chromosome.name.toLowerCase() === this.variant.analysisResult.chromosomes[i]);
let itemsLengthAtChromosome = 0;
const genes = {};
const geneNames = [];
const visualBreakpoints = [];
let prevGene = null;
let prevPosition = null;
let maxTranscriptsPerChromosome = 0;
let emptyGenesLength = 0;
for (let j = 0; j < breakpointsAtChromosome.length; j++) {
const breakpoint = breakpointsAtChromosome[j];
if (breakpoint.affectedGene !== undefined && breakpoint.affectedGene !== null) {
const affectedGene = breakpoint.affectedGene;
if (!affectedGene.empty) {
if (maxTranscriptsPerChromosome < affectedGene.transcripts.length) {
maxTranscriptsPerChromosome = affectedGene.transcripts.length;
}
}
if (prevGene && prevPosition && (prevGene.empty || affectedGene.empty || prevGene.name !== affectedGene.name)) {
const left = {
gene: prevGene,
range: {
start: prevPosition,
end: prevGene.empty ? emptyGeneSize : prevGene.totalExonsLength
}
};
const right = {
gene: affectedGene,
range: {
start: affectedGene.empty ? 0 : breakpoint.relativePositions[affectedGene.name],
end: affectedGene.empty ? emptyGeneSize / 2 : affectedGene.totalExonsLength
}
};
visualBreakpoints.push({
left,
right
});
}
const left = {
gene: affectedGene,
range: {
start: affectedGene.empty ? 0 : ((prevGene && prevGene.name === affectedGene.name) ? prevPosition : 0),
end: affectedGene.empty ? emptyGeneSize / 2 : breakpoint.relativePositions[breakpoint.affectedGene.name]
}
};
const right = {
gene: affectedGene,
range: {
start: affectedGene.empty ? emptyGeneSize / 2 : breakpoint.relativePositions[breakpoint.affectedGene.name],
end: affectedGene.empty ? emptyGeneSize : affectedGene.totalExonsLength
}
};
visualBreakpoints.push({
left,
right,
dataBreakpoint: breakpoint
});
prevGene = affectedGene;
prevPosition = affectedGene.empty ? emptyGeneSize / 2 : breakpoint.relativePositions[breakpoint.affectedGene.name];
if (affectedGene.empty) {
emptyGenesLength += emptyGeneSize;
}
else {
if (!genes.hasOwnProperty(affectedGene.name)) {
genes[affectedGene.name] = 0;
geneNames.push(affectedGene.name);
}
let itemsLengthAtGene = 0;
for (let k = 0; k < affectedGene.consensusExons.length; k++) {
itemsLengthAtGene += (affectedGene.consensusExons[k].end - affectedGene.consensusExons[k].start);
}
genes[affectedGene.name] = itemsLengthAtGene;
}
}
}
subZone.zones.push({name: 'gene'});
subZone.zones.push({name: 'upper', zones: [{name: 'edges'}]});
subZone.zones.push({name: 'chromosome'});
subZone.zones.push({name: 'down', zones: [{name: 'edges'}]});
for (let j = 0; j < geneNames.length; j++) {
itemsLengthAtChromosome += genes[geneNames[j]];
}
itemsLengthAtChromosome += emptyGenesLength;
chromosomeVisualInfo[this.variant.analysisResult.chromosomes[i]] = {
itemsLength: itemsLengthAtChromosome,
visualBreakpoints: visualBreakpoints
};
if (maximumBreakpointsPerChromosome < visualBreakpoints.length) {
maximumBreakpointsPerChromosome = visualBreakpoints.length;
}
if (maximumItemsLength < itemsLengthAtChromosome) {
maximumItemsLength = itemsLengthAtChromosome;
}
}
if (maximumBreakpointsPerChromosome === 1) {
for (let i = 0; i < this.variant.analysisResult.chromosomes.length; i++) {
const chromosomeName = this.variant.analysisResult.chromosomes[i];
if (chromosomeVisualInfo[chromosomeName].visualBreakpoints.length === 1) {
const visualBreakpoint = chromosomeVisualInfo[chromosomeName].visualBreakpoints[0];
chromosomeVisualInfo[chromosomeName].leftPart = visualBreakpoint.left.range.end - visualBreakpoint.left.range.start;
if (visualBreakpoint.left.range.end - visualBreakpoint.left.range.start > maximumLeftLength) {
maximumLeftLength = visualBreakpoint.left.range.end - visualBreakpoint.left.range.start;
}
if (visualBreakpoint.right.range.end - visualBreakpoint.right.range.start > maximumRightLength) {
maximumRightLength = visualBreakpoint.right.range.end - visualBreakpoint.right.range.start;
}
}
}
maximumItemsLength = maximumLeftLength + maximumRightLength;
}
this._visualAreaOffset = this.config.reference.width + this.config.reference.margin.x + this.config.chromosome.margin + this.config.breakpoint.width / 2;
const offset = this._visualAreaOffset + maxChromosomeLabelSize;
this._mainOffset = offset - 5;
const usefulCanvasLength = config.width - maximumBreakpointsPerChromosome * this.config.breakpoint.width - 2 * offset;
const factor = usefulCanvasLength / maximumItemsLength;
const convertBpToPixels = (bp) => bp * factor;
const registerViewport = (name, bpRange, canvasStart) => {
const canvasParams = {
start: canvasStart,
end: canvasStart + convertBpToPixels(bpRange.end - bpRange.start)
};
const viewport = new BaseViewport({chromosome: bpRange, brush: bpRange, canvas: canvasParams});
let viewports = this.viewports.get(name.toUpperCase());
if (!viewports) {
viewports = [];
}
viewports.push(viewport);
this.viewports.set(name.toUpperCase(), viewports);
return viewport;
};
const registerViewportByRange = (name, bpRange, canvasRange) => {
const viewport = new BaseViewport({chromosome: bpRange, brush: bpRange, canvas: canvasRange});
let viewports = this.viewports.get(name.toUpperCase());
if (!viewports) {
viewports = [];
}
viewports.push(viewport);
this.viewports.set(name.toUpperCase(), viewports);
return viewport;
};
for (let i = 0; i < this.variant.analysisResult.geneNames.length; i++) {
const gene = this.variant.analysisResult.genes[this.variant.analysisResult.geneNames[i]].gene;
if (this._transcriptExpandedStatus[gene.name.toUpperCase()] === undefined) {
this._transcriptExpandedStatus[gene.name.toUpperCase()] = false;
}
const start = 0;
let end = null;
const zone = {
name: `${gene.name} transcripts`,
zones: [{name: 'transcriptLabel'}]
};
const geneTranscriptsZone = {
name: 'transcriptsZone',
zones: [],
expanded: this._transcriptExpandedStatus[gene.name.toUpperCase()]
};
zone.zones.push(geneTranscriptsZone);
geneTranscriptsZones.push(zone);
for (let j = 0; j < gene.transcripts.length; j++) {
const transcript = gene.transcripts[j];
for (let t = 0; t < transcript.canonicalCds.length; t++) {
const cds = transcript.canonicalCds[t];
if (end === null || end < cds.positionFromStart.end) {
end = cds.positionFromStart.end;
}
}
geneTranscriptsZone.zones.push({
name: `${gene.name}_transcript_${j}`,
zones: [{name: 'transcriptName'}, {name: 'transcript'}]
});
registerViewportByRange(`${gene.name}_transcript_${j}`,
{start, end},
{
start: offset + this.config.transcript.radio.radius * 2 +
this.config.transcript.radio.margin * 2,
end: config.width - offset
});
}
geneTranscriptsZone.zones.push({name: 'buffer'});
}
for (let i = 0; i < this.variant.analysisResult.chromosomes.length; i++) {
const chromosomeName = this.variant.analysisResult.chromosomes[i];
const chromosomeWidthPx = convertBpToPixels(chromosomeVisualInfo[chromosomeName].itemsLength) + chromosomeVisualInfo[chromosomeName].visualBreakpoints.length * this.config.breakpoint.width;
let startX = config.width / 2 - chromosomeWidthPx / 2;
if (chromosomeVisualInfo[chromosomeName].leftPart !== undefined) {
startX = offset + convertBpToPixels(maximumLeftLength - chromosomeVisualInfo[chromosomeName].leftPart);
}
for (let j = 0; j < chromosomeVisualInfo[chromosomeName].visualBreakpoints.length; j++) {
const visualBreakpoint = chromosomeVisualInfo[chromosomeName].visualBreakpoints[j];
if (j < chromosomeVisualInfo[chromosomeName].visualBreakpoints.length - 1) {
// left viewport
const viewportCanvasWidth = convertBpToPixels(visualBreakpoint.left.range.end - visualBreakpoint.left.range.start);
const viewport = registerViewport(`${chromosomeName}:${visualBreakpoint.left.gene.name}`, visualBreakpoint.left.range, startX);
startX += this.config.breakpoint.width + viewportCanvasWidth;
if (visualBreakpoint.dataBreakpoint) {
this._breakpointPositioning.set(visualBreakpoint.dataBreakpoint, {
start: viewport.canvas.end,
end: viewport.canvas.end + this.config.breakpoint.width
});
}
}
else {
// left & right viewports
const leftViewportCanvasWidth = convertBpToPixels(visualBreakpoint.left.range.end - visualBreakpoint.left.range.start);
const viewport = registerViewport(`${chromosomeName}:${visualBreakpoint.left.gene.name}`, visualBreakpoint.left.range, startX);
startX += this.config.breakpoint.width + leftViewportCanvasWidth;
if (visualBreakpoint.dataBreakpoint) {
this._breakpointPositioning.set(visualBreakpoint.dataBreakpoint, {
start: viewport.canvas.end,
end: viewport.canvas.end + this.config.breakpoint.width
});
}
const rightViewportCanvasWidth = convertBpToPixels(visualBreakpoint.right.range.end - visualBreakpoint.right.range.start);
registerViewport(`${chromosomeName}:${visualBreakpoint.right.gene.name}`, visualBreakpoint.right.range, startX);
startX += this.config.breakpoint.width + rightViewportCanvasWidth;
}
}
}
return [...geneTranscriptsZones, refZone];
}