cabb4fa228289aadbaf6a1a16461646fcb7aa774
braney
  Tue Apr 10 18:55:38 2012 -0700
interim check-in for #6152.   Adding variant structure and setup that allows maintaing multiple variants in one gp.
diff --git src/hg/lib/gpFx.c src/hg/lib/gpFx.c
index 1489b86..b30cd05 100644
--- src/hg/lib/gpFx.c
+++ src/hg/lib/gpFx.c
@@ -1,96 +1,157 @@
 
 #include "common.h"
-#include "pgSnp.h"
 #include "genePred.h"
 #include "gpFx.h"
 
-/* remember!
-getGPsWithFrames
-*/
-
-struct gpFx *gpFxInCodingExon(struct pgSnp *pgSnp, struct genePred *pred, 
-    int exonNum)
+struct gpFx *gpFxInCodingExon(struct variant *variant, struct genePred *pred, 
+    int exonNum, char **returnTranscript, char **returnCoding)
 {
+//if ((pred->optFields & genePredExonFramesFld) == 0)
+ //   genePredAddExonFrames(pred);
+
 return NULL;
 }
 
-struct gpFx *gpFxInExon(struct pgSnp *pgSnp, struct genePred *pred, 
-    int exonNum)
+struct gpFx *gpFxInExon(struct variant *variant, struct genePred *pred, 
+    int exonNum, char **returnTranscript, char **returnCoding)
 {
-struct gpFx *effectsList = NULL, *effects;
+struct gpFx *effectsList = NULL;
 
 if (positiveRangeIntersection(pred->cdsStart, pred->cdsEnd,
-	pgSnp->chromStart, pgSnp->chromEnd))
+	variant->chromStart, variant->chromEnd))
     {
     // we're in CDS
-    effects = gpFxInCodingExon(pgSnp, pred, exonNum);
-    if (effects)
-	slAddHead(&effectsList, effects);
+    effectsList = slCat(effectsList, gpFxInCodingExon(variant, pred, exonNum,
+	    returnTranscript, returnCoding));
     }
 
 if (positiveRangeIntersection(pred->txStart, pred->cdsStart,
-	pgSnp->chromStart, pgSnp->chromEnd))
+	variant->chromStart, variant->chromEnd))
     {
-    // we're in 5' UTR
+    // we're in 5' UTR ( or UTR intron )
     }
 
 if (positiveRangeIntersection(pred->txStart, pred->cdsStart,
-	pgSnp->chromStart, pgSnp->chromEnd))
+	variant->chromStart, variant->chromEnd))
     {
     // we're in 3' UTR
     }
 
 return effectsList;
 }
 
-struct gpFx *gpFxCheckExons(struct pgSnp *pgSnp, struct genePred *pred)
-// check to see if the pgSnp is in an exon or an intron
+
+static struct gpFx *gpFxCheckExons(struct variant *variant, 
+    struct genePred *pred, char **returnTranscript, char **returnCoding)
+// check to see if the variant is in an exon
 {
 int ii;
-struct gpFx *effectsList = NULL, *effects;
+struct gpFx *effectsList = NULL;
 
+for(; variant ; variant = variant->next)
+    {
 for(ii=0; ii < pred->exonCount; ii++)
     {
     // check if in an exon
     if (positiveRangeIntersection(pred->exonStarts[ii], pred->exonEnds[ii], 
-	    pgSnp->chromStart, pgSnp->chromEnd))
+		variant->chromStart, variant->chromEnd))
 	{
-	effects = gpFxInExon(pgSnp, pred, ii);
-	if (effects)
-	    slAddHead(&effectsList, effects);
+	    // we know we've changed the transcript, start to track it
+
+	    effectsList = slCat(effectsList, gpFxInExon(variant, pred, ii,
+		returnTranscript, returnCoding));
+	    }
+	}
 	}
 
-    // check if in intron
-    if (ii < pred->exonCount - 1)
+return effectsList;
+}
+
+static struct gpFx *gpFxCheckIntrons(struct variant *variant, 
+    struct genePred *pred)
+// check to see if a single variant is in an exon or an intron
 	{
+int ii;
+struct gpFx *effectsList = NULL;
+
+for(ii=0; ii < pred->exonCount - 1; ii++)
+    {
+    // check if in intron
 	if (positiveRangeIntersection(pred->exonEnds[ii], 
 		pred->exonStarts[ii+1],
-		pgSnp->chromStart, pgSnp->chromEnd))
+	    variant->chromStart, variant->chromEnd))
 	    {
+	struct gpFx *effects;
 	    AllocVar(effects);
 	    effects->gpFxType = gpFxIntron;
 	    effects->gpFxNumber = ii;
 	    slAddHead(&effectsList, effects);
 	    }
 	}
+
+return effectsList;
+}
+
+
+static struct gpFx *gpFxCheckBackground(struct variant *variant, 
+    struct genePred *pred)
+// check to see if the variant is up or downstream or in intron of the gene 
+{
+struct gpFx *effectsList = NULL, *effects;
+
+for(; variant ; variant = variant->next)
+    {
+    // is this variant in an intron
+    effectsList = slCat(effectsList, gpFxCheckIntrons(variant, pred));
+
+    if (positiveRangeIntersection(pred->txStart - GPRANGE, pred->txStart,
+	    variant->chromStart, variant->chromEnd))
+	{
+	AllocVar(effects);
+	if (*pred->strand == '+')
+	    effects->gpFxType = gpFxUpstream;
+	else
+	    effects->gpFxType = gpFxDownstream;
+	effectsList = slCat(effectsList, effects);
+	}
+
+    if (positiveRangeIntersection(pred->txEnd, pred->txEnd + GPRANGE,
+	    variant->chromStart, variant->chromEnd))
+	{
+	AllocVar(effects);
+	if (*pred->strand == '+')
+	    effects->gpFxType = gpFxDownstream;
+	else
+	    effects->gpFxType = gpFxUpstream;
+	effectsList = slCat(effectsList, effects);
+	}
     }
 
 return effectsList;
 }
 
-struct gpFx *gpFxPredEffect(struct pgSnp *pgSnp, struct genePred *pred)
-// return the predicted effect(s) of a variation on a genePred
+struct gpFx *gpFxPredEffect(struct variant *variant, struct genePred *pred,
+    char **returnTranscript, char **returnCoding)
+// return the predicted effect(s) of a variation list on a genePred
 {
-// first check to see if SNP is in an exon
-struct gpFx *effects = gpFxCheckExons(pgSnp, pred);
+struct gpFx *effectsList = NULL;
+
+// check to see if SNP is up or downstream in intron 
+effectsList = slCat(effectsList, gpFxCheckBackground(variant, pred));
 
-if (effects != NULL)
-    return effects;
+// check to see if SNP is in the transcript
+effectsList = slCat(effectsList, gpFxCheckExons(variant, pred, 
+    returnTranscript, returnCoding));
+
+if (effectsList != NULL)
+    return effectsList;
 
 // default is no effect
-static struct gpFx noEffect;
-noEffect.next = NULL;
-noEffect.gpFxType = gpFxNone;
+struct gpFx *noEffect;
+
+AllocVar(noEffect);
+noEffect->next = NULL;
+noEffect->gpFxType = gpFxNone;
 
-return &noEffect;
+return noEffect;
 }