7f7a9a5579d7acec698c51dbf93f5030ce1a0439
braney
  Tue Apr 8 15:43:17 2025 -0700
support genePred in quickLift

diff --git src/hg/lib/liftOver.c src/hg/lib/liftOver.c
index 088a34dd388..659bf7b6408 100644
--- src/hg/lib/liftOver.c
+++ src/hg/lib/liftOver.c
@@ -1663,91 +1663,100 @@
 bed->thickStart = gp->cdsStart;
 bed->thickEnd = gp->cdsEnd;
 bed->blockCount = count = gp->exonCount;
 AllocArray(bed->blockSizes, count);
 AllocArray(bed->chromStarts, count);
 for (i=0; i<count; ++i)
     {
     int s = gp->exonStarts[i];
     int e = gp->exonEnds[i];
     bed->blockSizes[i] = e - s;
     bed->chromStarts[i] = s - start;
     }
 return bed;
 }
 
-void liftOverGenePred(char *fileName, struct hash *chainHash, 
+void calcLiftOverGenePreds( struct genePred *gpList, struct hash *chainHash, 
                         double minMatch, double minBlocks, bool fudgeThick,
                       FILE *mapped, FILE *unmapped, boolean multiple, bool preserveInput)
-/* Lift over file in genePred format. */
+/* worker function for liftOverGenePred. */
 {
 char *db = NULL, *chainTable = NULL;
 
 struct bed *bed;
 struct genePred *gp = NULL;
 char *error;
-struct genePred *gpList = genePredExtLoadAll(fileName);
 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);
     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)
 	{
-	fprintf(unmapped, "# %s\n", error);
         bedFree(&bed);
+        if (unmapped)
+            {
+            fprintf(unmapped, "# %s\n", error);
             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->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 (mapped)
                 genePredTabOut(gp, mapped);
 	    }
         bedFreeList(&bedList);
 	}
-//    genePredFree(&gp);
     }
 }
 
+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);
+}
+
 static struct liftRange *sampleToRangeList(struct sample *sample, int sizeOne)
 /* Make a range list corresponding to sample. */
 {
 int i;
 struct liftRange *rangeList = NULL, *range;
 for (i=0; i<sample->sampleCount; ++i)
     {
     AllocVar(range);
     range->start = range->end = sample->chromStart + sample->samplePosition[i];
     range->end += sizeOne;
     range->val = sample->sampleHeight[i];
     slAddHead(&rangeList, range);
     }
 slReverse(&rangeList);
 return rangeList;