Skip to content

Commit 8828bf9

Browse files
authored
Render LASFD exon-connecting lines regardless of exon width (#730)
* render exon connecting lines even when cds px width < 2 * ensure hover highlighting of exon-connecting lines is also outside of the width>2 gate
1 parent 2600980 commit 8828bf9

File tree

1 file changed

+57
-59
lines changed
  • packages/jbrowse-plugin-apollo/src/LinearApolloSixFrameDisplay/glyphs

1 file changed

+57
-59
lines changed

packages/jbrowse-plugin-apollo/src/LinearApolloSixFrameDisplay/glyphs/GeneGlyph.ts

Lines changed: 57 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,30 @@ function draw(
351351
(frame < 0 ? -1 * frame + 5 : frame) * featureLabelSpacer
352352
cdsTop = (frameAdjust - featureLabelSpacer) * rowHeight
353353
ctx.fillRect(cdsStartPx, cdsTop, cdsWidthPx, cdsHeight)
354+
355+
// Draw lines to connect CDS features with shared mRNA parent
356+
if (counter > 1) {
357+
// Mid-point for intron line "hat"
358+
const midPoint: [number, number] = [
359+
(cdsStartPx - prevCDSEndPx) / 2 + prevCDSEndPx,
360+
Math.max(
361+
frame < 0 ? rowHeight * featureLabelSpacer * highestRow + 1 : 1, // Avoid render ceiling
362+
Math.min(prevCDSTop, cdsTop) - rowHeight / 2,
363+
),
364+
]
365+
ctx.strokeStyle = 'rgb(0, 128, 128)'
366+
ctx.beginPath()
367+
ctx.moveTo(prevCDSEndPx, prevCDSTop)
368+
ctx.lineTo(...midPoint)
369+
ctx.stroke()
370+
ctx.moveTo(...midPoint)
371+
ctx.lineTo(cdsStartPx, cdsTop + rowHeight / 2)
372+
ctx.stroke()
373+
}
374+
prevCDSEndPx = cdsStartPx + cdsWidthPx
375+
prevCDSTop = cdsTop + rowHeight / 2
376+
counter += 1
377+
354378
if (cdsWidthPx > 2) {
355379
ctx.clearRect(
356380
cdsStartPx + 1,
@@ -375,31 +399,6 @@ function draw(
375399
cdsHeight - 2,
376400
)
377401

378-
// Draw lines to connect CDS features with shared mRNA parent
379-
if (counter > 1) {
380-
// Mid-point for intron line "hat"
381-
const midPoint: [number, number] = [
382-
(cdsStartPx - prevCDSEndPx) / 2 + prevCDSEndPx,
383-
Math.max(
384-
frame < 0
385-
? rowHeight * featureLabelSpacer * highestRow + 1
386-
: 1, // Avoid render ceiling
387-
Math.min(prevCDSTop, cdsTop) - rowHeight / 2,
388-
),
389-
]
390-
ctx.strokeStyle = 'rgb(0, 128, 128)'
391-
ctx.beginPath()
392-
ctx.moveTo(prevCDSEndPx, prevCDSTop)
393-
ctx.lineTo(...midPoint)
394-
ctx.stroke()
395-
ctx.moveTo(...midPoint)
396-
ctx.lineTo(cdsStartPx, cdsTop + rowHeight / 2)
397-
ctx.stroke()
398-
}
399-
prevCDSEndPx = cdsStartPx + cdsWidthPx
400-
prevCDSTop = cdsTop + rowHeight / 2
401-
counter += 1
402-
403402
if (topFill && bottomFill) {
404403
ctx.fillStyle = topFill
405404
ctx.fillRect(
@@ -518,43 +517,42 @@ function drawHover(
518517
let counter = 1
519518
for (const cds of cdsRow.sort((a, b) => a.max - b.max)) {
520519
const cdsWidthPx = (cds.max - cds.min) / bpPerPx
520+
const minX =
521+
(lgv.bpToPx({
522+
refName,
523+
coord: cds.min,
524+
regionNumber: layoutIndex,
525+
})?.offsetPx ?? 0) - offsetPx
526+
const cdsStartPx = reversed ? minX - cdsWidthPx : minX
527+
const frame = getFrame(cds.min, cds.max, strand ?? 1, cds.phase)
528+
const frameAdjust =
529+
(frame < 0 ? -1 * frame + 5 : frame) * featureLabelSpacer
530+
const cdsTop = (frameAdjust - featureLabelSpacer) * rowHeight
531+
if (counter > 1) {
532+
// Mid-point for intron line "hat"
533+
const midPoint: [number, number] = [
534+
(cdsStartPx - prevCDSEndPx) / 2 + prevCDSEndPx,
535+
Math.max(
536+
frame < 0 ? rowHeight * featureLabelSpacer * highestRow + 1 : 1, // Avoid render ceiling
537+
Math.min(prevCDSTop, cdsTop) - rowHeight / 2,
538+
),
539+
]
540+
ctx.strokeStyle = 'rgb(0, 0, 0)'
541+
ctx.lineWidth = 2
542+
ctx.beginPath()
543+
ctx.moveTo(prevCDSEndPx, prevCDSTop)
544+
ctx.lineTo(...midPoint)
545+
ctx.stroke()
546+
ctx.moveTo(...midPoint)
547+
ctx.lineTo(cdsStartPx, cdsTop + rowHeight / 2)
548+
ctx.stroke()
549+
}
550+
prevCDSEndPx = cdsStartPx + cdsWidthPx
551+
prevCDSTop = cdsTop + rowHeight / 2
552+
counter += 1
521553
if (cdsWidthPx > 2) {
522-
const minX =
523-
(lgv.bpToPx({
524-
refName,
525-
coord: cds.min,
526-
regionNumber: layoutIndex,
527-
})?.offsetPx ?? 0) - offsetPx
528-
const cdsStartPx = reversed ? minX - cdsWidthPx : minX
529-
const frame = getFrame(cds.min, cds.max, strand ?? 1, cds.phase)
530-
const frameAdjust =
531-
(frame < 0 ? -1 * frame + 5 : frame) * featureLabelSpacer
532-
const cdsTop = (frameAdjust - featureLabelSpacer) * rowHeight
533554
ctx.fillStyle = 'rgba(255,0,0,0.6)'
534555
ctx.fillRect(cdsStartPx, cdsTop, cdsWidthPx, cdsHeight)
535-
536-
if (counter > 1) {
537-
// Mid-point for intron line "hat"
538-
const midPoint: [number, number] = [
539-
(cdsStartPx - prevCDSEndPx) / 2 + prevCDSEndPx,
540-
Math.max(
541-
frame < 0 ? rowHeight * featureLabelSpacer * highestRow + 1 : 1, // Avoid render ceiling
542-
Math.min(prevCDSTop, cdsTop) - rowHeight / 2,
543-
),
544-
]
545-
ctx.strokeStyle = 'rgb(0, 0, 0)'
546-
ctx.lineWidth = 2
547-
ctx.beginPath()
548-
ctx.moveTo(prevCDSEndPx, prevCDSTop)
549-
ctx.lineTo(...midPoint)
550-
ctx.stroke()
551-
ctx.moveTo(...midPoint)
552-
ctx.lineTo(cdsStartPx, cdsTop + rowHeight / 2)
553-
ctx.stroke()
554-
}
555-
prevCDSEndPx = cdsStartPx + cdsWidthPx
556-
prevCDSTop = cdsTop + rowHeight / 2
557-
counter += 1
558556
}
559557
}
560558
}

0 commit comments

Comments
 (0)