3070de3ae68503b4913f650584ee86aa606b5592 angie Mon Apr 28 16:03:21 2025 -0700 Fix corner case (exonic portion of alt in deletion spanning end of transcript) found in #35577 diff --git src/hg/lib/variantProjector.c src/hg/lib/variantProjector.c index ac227e283c9..e74e5f07a9f 100644 --- src/hg/lib/variantProjector.c +++ src/hg/lib/variantProjector.c @@ -1708,30 +1708,41 @@ vpTxEx->end.aliBlkIx = isRc ? vpTxIn->end.aliBlkIx + 1 : vpTxIn->end.aliBlkIx; else vpTxEx->end.aliBlkIx = vpTxIn->end.aliBlkIx; gSeqTrim = vpTxIn->end.gDistance; } vpTxEx->txName = cloneString(vpTxIn->txName); // Truncate alleles to just the exon part. int gRefLen = strlen(vpTxIn->gRef); if (gRefLen <= gSeqOffset) vpTxEx->gRef = cloneString(""); else vpTxEx->gRef = cloneStringZ(vpTxIn->gRef + gSeqOffset, gRefLen - gSeqOffset - gSeqTrim); int gAltLen = strlen(vpTxIn->gAlt); if (gAltLen <= gSeqOffset) vpTxEx->gAlt = cloneString(""); +else if (gAltLen < gRefLen) + { + // If it's a deletion then we can't just apply the same -gSeqTrim adjustment to alt as to ref + // or else we could underflow. Clip to the in-exon length that we used for vpTxEx->gRef. + // In real life, who knows what would happen to the exon boundary, but at least this is + // consistent with txAlt length. VAI calls this complex_transcript_variant. #35577 note 14 + int exonAltLen = gAltLen - gSeqOffset; + if (exonAltLen > gRefLen - gSeqOffset - gSeqTrim) + exonAltLen = gRefLen - gSeqOffset - gSeqTrim; + vpTxEx->gAlt = cloneStringZ(vpTxIn->gAlt + gSeqOffset, exonAltLen); + } else vpTxEx->gAlt = cloneStringZ(vpTxIn->gAlt + gSeqOffset, gAltLen - gSeqOffset - gSeqTrim); vpTxEx->txRef = cloneString(vpTxIn->txRef); vpTxEx->txAlt = cloneString(vpTxIn->txAlt); vpTxEx->basesShifted = vpTxIn->basesShifted; vpTxEx->genomeMismatch = vpTxIn->genomeMismatch; return vpTxEx; } static struct vpTx *vpTxNewIntronPart(struct vpTx *vpTxIn, struct psl *psl) /* vpTxIn either starts or ends in an intron; return a new vpTx that contains only the * intronic part. */ { enum vpTxRegion startRegion = vpTxIn->start.region; enum vpTxRegion endRegion = vpTxIn->end.region;