UNPKG

@jbrowse/plugin-wiggle

Version:

JBrowse 2 wiggle adapters, tracks, etc.

75 lines (74 loc) 2.9 kB
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, }; }