higlass
Version:
HiGlass Hi-C / genomic / large data viewer
182 lines (138 loc) • 4.76 kB
JavaScript
// @ts-nocheck
import boxIntersect from 'box-intersect';
import ChromosomeInfo from './ChromosomeInfo';
import PixiTrack from './PixiTrack';
import SearchField from './SearchField';
import { absToChr } from './utils';
// Configs
import { GLOBALS } from './configs';
class Chromosome2DLabels extends PixiTrack {
constructor(context, options) {
super(context, options);
const { dataConfig, animate, pubSub } = context;
this.searchField = null;
this.chromInfo = null;
this.animate = animate;
const server = dataConfig.server;
const uid = dataConfig.tilesetUid;
const chromSizesPath = `${server}/chrom-sizes/?id=${uid}`;
ChromosomeInfo(
chromSizesPath,
(newChromInfo) => {
this.chromInfo = newChromInfo;
//
this.searchField = new SearchField(this.chromInfo);
this.draw();
this.texts = [];
for (let i = 0; i < this.chromInfo.cumPositions.length; i++) {
const thisTexts = [];
for (let j = 0; j < this.chromInfo.cumPositions.length; j++) {
const textStr = `${this.chromInfo.cumPositions[i].chr}/${this.chromInfo.cumPositions[j].chr}`;
const text = new GLOBALS.PIXI.Text(textStr, {
fontSize: '14px',
fontFamily: 'Arial',
fill: 'red',
});
text.anchor.x = 0.5;
text.anchor.y = 0.5;
text.visible = false;
// give each string a random hash so that some get hidden
// when there's overlaps
text.hashValue = Math.random();
thisTexts.push(text);
this.pMain.addChild(text);
}
this.texts.push(thisTexts);
}
this.draw();
this.animate();
},
pubSub,
);
}
draw() {
const allTexts = [];
if (!this.texts) {
return;
}
if (!this.searchField) {
return;
}
const x1 = absToChr(this._xScale.domain()[0], this.chromInfo);
const x2 = absToChr(this._xScale.domain()[1], this.chromInfo);
const y1 = absToChr(this._yScale.domain()[0], this.chromInfo);
const y2 = absToChr(this._yScale.domain()[1], this.chromInfo);
for (let i = 0; i < this.texts.length; i++) {
for (let j = 0; j < this.texts.length; j++) {
this.texts[i][j].visible = false;
}
}
for (let i = x1[3]; i <= x2[3]; i++) {
for (let j = y1[3]; j <= y2[3]; j++) {
const xCumPos = this.chromInfo.cumPositions[i];
const yCumPos = this.chromInfo.cumPositions[j];
const midX = xCumPos.pos + this.chromInfo.chromLengths[xCumPos.chr] / 2;
const midY = yCumPos.pos + this.chromInfo.chromLengths[yCumPos.chr] / 2;
const viewportMidX = this._xScale(midX);
const viewportMidY = this._yScale(midY);
const text = this.texts[i][j];
text.x = viewportMidX;
text.y = viewportMidY;
text.updateTransform();
const bbox = text.getBounds();
const bwh = bbox.width / 2;
const bhh = bbox.height / 2;
// make sure the chrosome label fits in the x range
if (viewportMidX + bwh > this.dimensions[0]) {
text.x -= viewportMidX + bwh - this.dimensions[0];
} else if (viewportMidX - bwh < 0) {
//
text.x -= viewportMidX - bwh;
}
// make sure the chro
if (viewportMidY + bhh > this.dimensions[1]) {
text.y -= viewportMidY + bhh - this.dimensions[1];
} else if (viewportMidY - bhh < 0) {
text.y -= viewportMidY - bhh;
}
text.visible = true;
allTexts.push({
importance: this.texts[i][j].hashValue,
text: this.texts[i][j],
caption: null,
});
}
}
// define the edge chromosome which are visible
this.hideOverlaps(allTexts);
}
hideOverlaps(allTexts) {
let allBoxes = []; // store the bounding boxes of the text objects so we can
// calculate overlaps
allBoxes = allTexts.map((val) => {
const text = val.text;
text.updateTransform();
const b = text.getBounds();
const box = [b.x, b.y, b.x + b.width, b.y + b.height];
return box;
});
boxIntersect(allBoxes, (i, j) => {
if (allTexts[i].importance > allTexts[j].importance) {
allTexts[j].text.visible = 0;
} else {
allTexts[i].text.visible = 0;
}
});
}
setPosition(newPosition) {
super.setPosition(newPosition);
this.pMain.position.y = this.position[1];
this.pMain.position.x = this.position[0];
}
zoomed(newXScale, newYScale) {
this.xScale(newXScale);
this.yScale(newYScale);
this.draw();
}
}
export default Chromosome2DLabels;