@jbrowse/plugin-wiggle
Version:
JBrowse 2 wiggle adapters, tracks, etc.
75 lines (74 loc) • 2.9 kB
JavaScript
import { readConfObject } from '@jbrowse/core/configuration';
import { clamp, featureSpanPx } from '@jbrowse/core/util';
import { checkStopToken } from '@jbrowse/core/util/stopToken';
import { getScale } from './util';
const fudgeFactor = 0.3;
const clipHeight = 2;
export function drawLine(ctx, props) {
const { features, regions, bpPerPx, scaleOpts, height: unadjustedHeight, ticks: { values }, displayCrossHatches, colorCallback, config, offset = 0, stopToken, } = props;
const region = regions[0];
const width = (region.end - region.start) / bpPerPx;
const height = unadjustedHeight - offset * 2;
const clipColor = readConfObject(config, 'clipColor');
const scale = getScale({ ...scaleOpts, range: [0, height] });
const domain = scale.domain();
const niceMin = domain[0];
const niceMax = domain[1];
const toY = (n) => clamp(height - (scale(n) || 0), 0, height) + offset;
let lastVal;
let prevLeftPx = Number.NEGATIVE_INFINITY;
const reducedFeatures = [];
let start = performance.now();
for (const feature of features.values()) {
if (performance.now() - start > 400) {
checkStopToken(stopToken);
start = performance.now();
}
const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
if (Math.floor(leftPx) !== Math.floor(prevLeftPx) || rightPx - leftPx > 1) {
reducedFeatures.push(feature);
prevLeftPx = leftPx;
}
const score = feature.get('score');
const lowClipping = score < niceMin;
const highClipping = score > niceMax;
const w = rightPx - leftPx + fudgeFactor;
const c = colorCallback(feature, score);
ctx.beginPath();
ctx.strokeStyle = c;
const startPos = lastVal !== undefined ? lastVal : score;
if (!region.reversed) {
ctx.moveTo(leftPx, toY(startPos));
ctx.lineTo(leftPx, toY(score));
ctx.lineTo(rightPx, toY(score));
}
else {
ctx.moveTo(rightPx, toY(startPos));
ctx.lineTo(rightPx, toY(score));
ctx.lineTo(leftPx, toY(score));
}
ctx.stroke();
lastVal = score;
if (highClipping) {
ctx.fillStyle = clipColor;
ctx.fillRect(leftPx, offset, w, clipHeight);
}
else if (lowClipping && scaleOpts.scaleType !== 'log') {
ctx.fillStyle = clipColor;
ctx.fillRect(leftPx, height - clipHeight, w, height);
}
}
if (displayCrossHatches) {
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgba(200,200,200,0.5)';
for (const tick of values) {
ctx.beginPath();
ctx.moveTo(0, Math.round(toY(tick)));
ctx.lineTo(width, Math.round(toY(tick)));
ctx.stroke();
}
}
return {
reducedFeatures,
};
}