e745ccb794a88cf79f4e63a375a3eeb93e918563
braney
  Mon Jan 26 10:15:44 2026 -0800
move code to reverse exonFrames to calcLiftOverGenePred() so it will
work with the liftOver tool

diff --git src/hg/lib/liftOver.c src/hg/lib/liftOver.c
index 8b7eafc1b84..d8bcafa986b 100644
--- src/hg/lib/liftOver.c
+++ src/hg/lib/liftOver.c
@@ -1072,31 +1072,31 @@
  * through chain.  This nulls out *pRangelist after modifying and freeing the contents. */
 {
 *retError = NULL;
 /* See if best one is good enough. */
 if (chain->score  < minMatch * bedSize)
     *retError = "Partially deleted in new";
 
 struct liftRange *rangeList = *pRangeList, *badRanges = NULL, *range;
 int thickStart = bed->thickStart;
 int thickEnd = bed->thickEnd;
 if (*retError == NULL)
     remapRangeList(chain, &rangeList, &thickStart, &thickEnd, minBlocks, fudgeThick,
                    &rangeList, &badRanges, retError);
 
 /* Convert rangeList back to bed blocks.  Also calculate start and end. */
-if (*retError == NULL)
+if ((*retError == NULL) && (rangeList != NULL))
     {
     int i, start, end = rangeList->end;
     if (chain->qStrand == '-')
 	{
 	rangeList = reverseRangeList(rangeList, chain->qSize);
 	reverseIntRange(&thickStart, &thickEnd, chain->qSize);
 	bed->strand[0] = otherStrand(bed->strand[0]);
 	}
     bed->chromStart = start = rangeList->start;
     //if (slCount(rangeList) > 1)
     if (bed->blockSizes != NULL)
         {
         bed->blockCount = slCount(rangeList);
         for (i=0, range = rangeList; range != NULL; range = range->next, ++i)
             {
@@ -1675,30 +1675,31 @@
 }
 
 void calcLiftOverGenePreds( struct genePred *gpList, struct hash *chainHash, 
                         double minMatch, double minBlocks, bool fudgeThick,
                       FILE *mapped, FILE *unmapped, boolean multiple, bool preserveInput)
 /* worker function for liftOverGenePred. */
 {
 char *db = NULL, *chainTable = NULL;
 
 struct bed *bed;
 struct genePred *gp = NULL;
 char *error;
 for (gp = gpList ; gp != NULL ; gp = gp->next)
     {
     // uglyf("%s %s %d %d %s\n", gp->name, gp->chrom, gp->txStart, gp->txEnd, gp->strand);
+    char origStrand = gp->strand[0];
     if (preserveInput)
         {
         char *old = gp->name;
         gp->name = extendNameWithPosition(gp->name, gp->chrom, gp->txStart, gp->txEnd, TRUE);
         free(old); // genePredExtLoadAll uses cloneString to populate this
         }
     bed = genePredToBed(gp);
     error = remapBlockedBed(chainHash, bed, minMatch, minBlocks, fudgeThick,
                             multiple, db, chainTable);
     if (error)
 	{
         gp->chrom = NULL; // this gp didn't get lifted so we want to make sure the caller can figure that out
         bedFree(&bed);
         if (unmapped)
             {
@@ -1706,43 +1707,46 @@
             genePredTabOut(gp, unmapped);
             }
 	}
    else
 	{
         int exonCount = gp->exonCount;
         struct bed *bedList = bed;
         for (;  bed != NULL;  bed = bed->next)
             {
             if (bed->blockCount > exonCount)
                 errAbort("program error: need to allocate extra blocks for bed.");
             freeMem(gp->chrom);
             gp->chrom = cloneString(bed->chrom);
             int start = gp->txStart = bed->chromStart;
             gp->txEnd = bed->chromEnd;
-            gp->origStrand = gp->strand[0];
+            //gp->origStrand = gp->strand[0];
             gp->strand[0] = bed->strand[0];
             gp->cdsStart = bed->thickStart;
             gp->cdsEnd = bed->thickEnd;
             int count = gp->exonCount = bed->blockCount;
             int i;
             for (i=0; i<count; ++i)
                 {
                 int s = start + bed->chromStarts[i];
                 int e = s + bed->blockSizes[i];
                 gp->exonStarts[i] = s;
                 gp->exonEnds[i] = e;
                 }
+            if (gp->strand[0] != origStrand)
+                genePredReverseFrames(gp);
+
             if (mapped)
                 genePredTabOut(gp, mapped);
 	    }
         bedFreeList(&bedList);
 	}
     }
 }
 
 void liftOverGenePred(char *fileName, struct hash *chainHash, 
                         double minMatch, double minBlocks, bool fudgeThick,
                       FILE *mapped, FILE *unmapped, boolean multiple, bool preserveInput)
 {
 calcLiftOverGenePreds(genePredExtLoadAll(fileName), chainHash, minMatch, minBlocks, fudgeThick, mapped, unmapped, multiple, preserveInput);
 }