92ece3cd72148ce76aabda9d08dbd9618ff9792d
larrym
  Tue Feb 8 21:42:08 2011 -0800
add utility routines for zoomToCodon and zoomToExon
diff --git src/hg/lib/genePred.c src/hg/lib/genePred.c
index f5ce54f..c425114 100644
--- src/hg/lib/genePred.c
+++ src/hg/lib/genePred.c
@@ -1791,15 +1791,113 @@
     fprintf(f, "\t");
 
     /* Output chromStarts field */
     for (i=0; i<gp->exonCount; ++i)
 	{
 	int exonStart = gp->exonStarts[i];
 	int exonEnd = gp->exonEnds[i];
 	exonStart = max(start, exonStart);
 	exonEnd = min(end, exonEnd);
 	if (exonStart < exonEnd)
 	    fprintf(f, "%d,", exonStart - newStart);
 	}
     fprintf(f, "\n");
     }
 }
+
+boolean codonToPos(struct genePred *gp, unsigned num, int *start, int *end)
+{
+// map 1-based codon to genomic coordinates. If the codon crosses an exon junction, we return just the beginning (LHS) of the codon.
+// Returns true if we find the codon in given gene predition; start and end are set to appropriate three base region.
+
+int pos = -1;
+int i;
+int offset = -1;  // current 1-based offset in bases (not codons)
+if(gp->strand[0] == '+')
+    {
+    for(i = 0; i < gp->exonCount; i++)
+        {
+        if(gp->exonEnds[i] > gp->cdsStart && gp->exonStarts[i] < gp->cdsEnd)
+            {
+            int start, end;
+            if(offset == -1 && gp->cdsStart <= gp->exonEnds[i])
+                {
+                // start counting
+                start = gp->cdsStart;
+                offset = 1;
+                }
+            else
+                start = gp->exonStarts[i];
+            if(gp->cdsEnd < gp->exonEnds[i])
+                end = gp->cdsEnd;
+            else
+                end = gp->exonEnds[i];
+            int next = offset + end - start;
+            if(next > (num * 3 - 2))
+                {
+                pos = start + (((num - 1) * 3 + 1) - offset);
+                break;
+                }
+            else
+                offset = next;
+            }
+        }
+    }
+else
+    {
+    for(i = gp->exonCount - 1; i >= 0; i--)
+        {
+        if(gp->exonStarts[i] < gp->cdsEnd && gp->exonEnds[i] >= gp->cdsEnd)
+            {
+            int start, end; // start here is really the RHS, and end is the LHS
+            if(offset == -1 && gp->cdsEnd >= gp->exonStarts[i])
+                {
+                // start counting
+                start = gp->cdsEnd;
+                offset = 1;
+                }
+            else
+                start = gp->exonEnds[i];
+            if(gp->cdsStart > gp->exonStarts[i])
+                end = gp->cdsStart;
+            else
+                end = gp->exonStarts[i];
+            int next = offset + start - end;
+            if(next > num * 3)
+                {
+                pos = start - (num*3 - offset) - 1;
+                break;
+                }
+            else
+                offset = next;
+            }
+        }
+    }
+if(pos == -1)
+    return FALSE;
+else
+    {
+    *start = pos;
+    *end = pos + 3;
+    return TRUE;
+    }
+}
+
+boolean exonToPos(struct genePred *gp, unsigned num, int *start, int *end)
+{
+// map 1-based exon number to genomic coordinates.
+// Returns true if we find the exon in given gene predition; start and end are set to appropriate region.
+
+if(num == 0 || num > gp->exonCount)
+    return FALSE;
+else if(gp->strand[0] == '+')
+    {
+    *start = gp->exonStarts[num - 1];
+    *end = gp->exonEnds[num - 1];
+    }
+else
+    {
+    *start = gp->exonStarts[gp->exonCount - num];
+    *end = gp->exonEnds[gp->exonCount - num];
+    }
+return TRUE;
+}