896eb991fff50f44f18811a05171e36fa111163d
braney
  Thu Sep 24 17:13:20 2026 -0700
quickLift: leave empty blocks out of a protein alignment before lifting it, refs #38249

The UniProt bigPsl files store block sizes in bases, and pslFromBigPsl divides them by
three, so a block shorter than a codon loads with size 0.  pslTransMap rejects such an
alignment and aborts, which replaced the whole lifted SwissProt track with a BUG message.
About one alignment in eight has a block like this.  quickLiftPsl now lifts a copy with
the empty blocks removed.  quickLiftTester has a new case in the shape of Q96ME1-2.

diff --git src/hg/lib/tests/expected/quickLiftTest src/hg/lib/tests/expected/quickLiftTest
index 317c5d94a18..8506042b09a 100644
--- src/hg/lib/tests/expected/quickLiftTest
+++ src/hg/lib/tests/expected/quickLiftTest
@@ -1,49 +1,58 @@
 == protein, chain on the same strand
 chain: t=chrSrc:100-400 q=chrRef:100-400 qStrand=+ blocks 100-400/100-400
 before   100	0	0	0	0	0	0	0	++	prot	100	0	100	chrSrc	1000	100	400	1	100,	0,	100,
          strand='++' isProtein=1 qSize=100 blockSizes[0]=100 pslCheck errors=0
 lifted   100	0	0	0	0	0	0	0	++	prot	100	0	100	chrRef	1000	100	400	1	100,	0,	100,
          strand='++' isProtein=1 qSize=100 blockSizes[0]=100 pslCheck errors=0
 
 == protein, chain on the opposite strand
 chain: t=chrSrc:600-900 q=chrRef:600-900 qStrand=- blocks 600-900/600-900
 before   100	0	0	0	0	0	0	0	++	prot	100	0	100	chrSrc	1000	600	900	1	100,	0,	600,
          strand='++' isProtein=1 qSize=100 blockSizes[0]=100 pslCheck errors=0
 lifted   100	0	0	0	0	0	0	0	+-	prot	100	0	100	chrRef	1000	100	400	1	100,	0,	600,
          strand='+-' isProtein=1 qSize=100 blockSizes[0]=100 pslCheck errors=0
 
 == protein, chain gaps the reference
 chain: t=chrSrc:100-400 q=chrRef:100-401 qStrand=+ blocks 100-250/100-250 250-400/251-401
 before   100	0	0	0	0	0	0	0	++	prot	100	0	100	chrSrc	1000	100	400	1	100,	0,	100,
          strand='++' isProtein=1 qSize=100 blockSizes[0]=100 pslCheck errors=0
 lifted   100	0	0	0	0	0	1	1	++	prot	100	0	100	chrRef	1000	100	401	2	50,50,	0,50,	100,251,
          strand='++' isProtein=1 qSize=100 blockSizes[0]=50 pslCheck errors=0
 
 == protein, lift splits a codon
 chain: t=chrSrc:100-401 q=chrRef:100-400 qStrand=+ blocks 100-250/100-250 251-401/250-400
 before   100	0	0	0	0	0	0	0	++	prot	100	0	100	chrSrc	1000	100	400	1	100,	0,	100,
          strand='++' isProtein=1 qSize=100 blockSizes[0]=100 pslCheck errors=0
 lifted   299	0	0	0	1	1	0	0	+	prot	300	0	300	chrRef	1000	100	399	2	150,149,	0,151,	100,250,
          strand='+' isProtein=0 qSize=300 blockSizes[0]=150 pslCheck errors=0
 
 == mRNA, chain on the same strand
 chain: t=chrSrc:100-400 q=chrRef:100-400 qStrand=+ blocks 100-400/100-400
 before   300	0	0	0	0	0	0	0	+	mrna	300	0	300	chrSrc	1000	100	400	1	300,	0,	100,
          strand='+' isProtein=0 qSize=300 blockSizes[0]=300 pslCheck errors=0
 lifted   300	0	0	0	0	0	0	0	+	mrna	300	0	300	chrRef	1000	100	400	1	300,	0,	100,
          strand='+' isProtein=0 qSize=300 blockSizes[0]=300 pslCheck errors=0
 
 == mRNA, chain on the opposite strand
 chain: t=chrSrc:600-900 q=chrRef:600-900 qStrand=- blocks 600-900/600-900
 before   300	0	0	0	0	0	0	0	+	mrna	300	0	300	chrSrc	1000	600	900	1	300,	0,	600,
          strand='+' isProtein=0 qSize=300 blockSizes[0]=300 pslCheck errors=0
 lifted   300	0	0	0	0	0	0	0	-	mrna	300	0	300	chrRef	1000	100	400	1	300,	0,	100,
          strand='-' isProtein=0 qSize=300 blockSizes[0]=300 pslCheck errors=0
 
+== protein, a block shorter than a codon
+chain: t=chrSrc:100-700 q=chrRef:100-700 qStrand=+ blocks 100-700/100-700
+before   90	0	0	0	0	0	0	0	-+	prot	100	0	100	chrSrc	1000	100	400	2	0,90,	0,10,	100,130,
+Error: invalid PSL: prot:0-100 chrSrc:100-400 -+ before
+	prot query block 0 start 100 >= qEnd 100
+         strand='-+' isProtein=1 qSize=100 blockSizes[0]=0 pslCheck errors=1
+lifted   90	0	0	0	0	0	0	0	+-	prot	100	0	90	chrRef	1000	130	400	1	90,	0,	600,
+         strand='+-' isProtein=1 qSize=100 blockSizes[0]=90 pslCheck errors=0
+
 == no chain over the alignment
 chain: t=chrSrc:100-400 q=chrRef:100-400 qStrand=+ blocks 100-400/100-400
 before   100	0	0	0	0	0	0	0	++	prot	100	0	100	chrSrc	1000	700	1000	1	100,	0,	700,
          strand='++' isProtein=1 qSize=100 blockSizes[0]=100 pslCheck errors=0
 lifted   did not lift
 
 passed