2a99d78cddf4b7de673435f911262ee25b36c238
braney
  Sun Feb 12 14:14:18 2023 -0800
ongoing work on snake display for chains and psls

diff --git src/hg/hgTracks/chainTrack.c src/hg/hgTracks/chainTrack.c
index 817a005..da88e8d 100644
--- src/hg/hgTracks/chainTrack.c
+++ src/hg/hgTracks/chainTrack.c
@@ -8,30 +8,31 @@
 #include "common.h"
 #include "hash.h"
 #include "localmem.h"
 #include "linefile.h"
 #include "jksql.h"
 #include "hdb.h"
 #include "hgTracks.h"
 #include "chainBlock.h"
 #include "chainLink.h"
 #include "chainDb.h"
 #include "chainCart.h"
 #include "hgColors.h"
 #include "hubConnect.h"
 #include "chromAlias.h"
 #include "hgConfig.h"
+#include "snake.h"
 
 struct cartOptions
     {
     enum chainColorEnum chainColor; /*  ChromColors, ScoreColors, NoColors */
     int scoreFilter ; /* filter chains by score if > 0 */
     };
 
 struct sqlClosure
 {
 struct sqlConnection *conn;
 };
 
 struct bbClosure
 {
 struct bbiFile *bbi;
@@ -119,54 +120,46 @@
     lf = hashFindVal(hash, row[0]);
     if (lf != NULL)
 	{
 	lmAllocVar(lm, sf);
 	sf->start = sqlUnsigned(row[1]);
 	sf->end = sqlUnsigned(row[2]);
 	sf->qStart = sqlUnsigned(row[3]);
 	sf->qEnd = sf->qStart + (sf->end - sf->start);
 	slAddHead(&lf->components, sf);
 	}
     }
 sqlFreeResult(&sr);
 dyStringFree(&query);
 }
 
-void chainDraw(struct track *tg, int seqStart, int seqEnd,
-        struct hvGfx *hvg, int xOff, int yOff, int width,
-        MgFont *font, Color color, enum trackVisibility vis)
-/* Draw chained features. This loads up the simple features from
- * the chainLink table, calls linkedFeaturesDraw, and then
- * frees the simple features again. */
+static void loadLinks(struct track *tg, int seqStart, int seqEnd,
+        enum trackVisibility vis)
 {
 struct linkedFeatures *lf;
 struct simpleFeature *sf;
 struct lm *lm;
 struct hash *hash;	/* Hash of chain ids. */
 #ifdef OLD
 double scale = ((double)(winEnd - winStart))/width;
 #endif /* OLD */
 
 char fullName[64];
 int start, end, extra;
 struct simpleFeature *lastSf = NULL;
 int maxOverLeft = 0, maxOverRight = 0;
 int overLeft, overRight;
-
-if (tg->items == NULL)		/*Exit Early if nothing to do */
-    return;
-
 void *closure;
 struct sqlClosure sqlClosure;
 struct bbClosure bbClosure;
 linkRetrieveFunc queryFunc;
 if (tg->isBigBed)
     {
     closure = &bbClosure;
     queryFunc = doBbQuery;
     char *fileName = trackDbSetting(tg->tdb, "linkDataUrl");
     if (fileName == NULL)
         {
         warn("Cannot find linkDataUrl in custom track \"%s\"\n", tg->shortLabel);
         return;
         }
     struct bbiFile *bbi =  bigBedFileOpenAlias(fileName, chromAliasFindAliases);
@@ -206,31 +199,31 @@
 	    maxOverLeft = overLeft;
 	}
 #ifdef OLD
     else
 	{
 	lmAllocVar(lm, sf);
 	sf->start = lf->start;
 	sf->end = lf->end;
 	sf->grayIx = lf->grayIx;
 	lf->components = sf;
 	}
 #endif /* OLD */
     }
 
 /* if some chains are actually loaded */
-if (hash->size)
+if (hash->elCount) 
     {
     boolean isSplit = TRUE;
     /* Make up range query. */
     safef(fullName, sizeof fullName, "%s_%s", chromName, tg->table);
     if (isHubTrack(tg->table) || !hTableExists(database, fullName))
 	{
 	strcpy(fullName, tg->table);
 	isSplit = FALSE;
 	}
 
     /* in dense mode we don't draw the lines
      * so we don't need items off the screen
      */
     if (vis == tvDense)
 	queryFunc(closure, fullName, lm,  hash, seqStart, seqEnd, NULL, isSplit);
@@ -307,43 +300,64 @@
 	    if ((lf->components != NULL) && (lf->components->start > seqStart) && (lf->start < lf->components->start))
 		{
 		lmAllocVar(lm, sf);
 		sf->start = 0;
 		sf->end = 1;
 		sf->grayIx = lf->grayIx;
 		sf->qStart = lf->components->qStart;
 		sf->qEnd = sf->qStart + (sf->end - sf->start);
 		sf->next = lf->components;
 		lf->components = sf;
 		slSort(&lf->components, linkedFeaturesCmpStart);
 		}
 	    }
 	}
     }
-linkedFeaturesDraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width,
-	font, color, vis);
-/* Cleanup time. */
 for (lf = tg->items; lf != NULL; lf = lf->next)
-    lf->components = NULL;
+        {
+	if ((lf) && lf->orientation == -1)
+	    {
+            struct simpleFeature *sf = lf->components;
 
+            for(; sf; sf = sf->next)
+                {
+                int temp;
+
+                temp = sf->qStart;
+                sf->qStart = lf->qSize - sf->qEnd;
+                sf->qEnd = lf->qSize - temp;
+                }
+	    }
+        }
 if (tg->isBigBed)
     bbiFileClose(&bbClosure.bbi);
 else
     hFreeConn(&sqlClosure.conn);
+    }
+void chainDraw(struct track *tg, int seqStart, int seqEnd,
+        struct hvGfx *hvg, int xOff, int yOff, int width,
+        MgFont *font, Color color, enum trackVisibility vis)
+/* Draw chained features. This loads up the simple features from
+ * the chainLink table, calls linkedFeaturesDraw, and then
+ * frees the simple features again. */
+{
 
-lmCleanup(&lm);
-freeHash(&hash);
+if (tg->items == NULL)		/*Exit Early if nothing to do */
+    return;
+
+linkedFeaturesDraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width,
+	font, color, vis);
 }
 
 void bigChainLoadItems(struct track *tg)
 /* Load up all of the chains from correct table into tg->items
  * item list.  At this stage to conserve memory for other tracks
  * we don't load the links into the components list until draw time. */
 {
 struct linkedFeatures *list = NULL, *lf;
 int qs;
 char *optionChrStr;
 struct cartOptions *chainCart;
 
 chainCart = (struct cartOptions *) tg->extraUiData;
 
 optionChrStr = cartOptionalStringClosestToHome(cart, tg->tdb, FALSE,
@@ -399,30 +413,31 @@
 else if ((tg->visibility == tvDense) &&
 	(chainCart->chainColor == chainColorScoreColors))
     slSort(&list, chainCmpScore);
 else
     slReverse(&list);
 tg->items = list;
 
 bbiFileClose(&bbi);
 }
 
 void chainLoadItems(struct track *tg)
 /* Load up all of the chains from correct table into tg->items
  * item list.  At this stage to conserve memory for other tracks
  * we don't load the links into the components list until draw time. */
 {
+boolean doSnake = cartOrTdbBoolean(cart, tg->tdb, "doSnake" , FALSE);
 char *table = tg->table;
 struct chain chain;
 int rowOffset;
 char **row;
 struct sqlConnection *conn = hAllocConn(database);
 struct sqlResult *sr = NULL;
 struct linkedFeatures *list = NULL, *lf;
 int qs;
 char *optionChrStr;
 char extraWhere[128] ;
 struct cartOptions *chainCart;
 
 chainCart = (struct cartOptions *) tg->extraUiData;
 
 optionChrStr = skipLeadingSpaces(cartUsualStringClosestToHome(cart, tg->tdb,
@@ -471,47 +486,52 @@
 
     lf->filterColor = -1;
 
     if (chain.qStrand == '-')
 	{
 	lf->orientation = -1;
         qs = chain.qSize - chain.qEnd;
 	}
     else
         {
 	lf->orientation = 1;
 	qs = chain.qStart;
 	}
     int len = strlen(chain.qName) + 32;
     lf->name = needMem(len);
+    if (!doSnake)
         safef(lf->name, len, "%s %c %dk", chain.qName, chain.qStrand, qs/1000);
+    else
+        safef(lf->name, len, "%s", chain.qName);
     safef(buf, sizeof(buf), "%d", chain.id);
     lf->extra = cloneString(buf);
     slAddHead(&list, lf);
     }
 
 /* Make sure this is sorted if in full mode. Sort by score when
  * coloring by score and in dense */
 if (tg->visibility != tvDense)
     slSort(&list, linkedFeaturesCmpStart);
 else if ((tg->visibility == tvDense) &&
 	(chainCart->chainColor == chainColorScoreColors))
     slSort(&list, chainCmpScore);
 else
     slReverse(&list);
 tg->items = list;
+loadLinks(tg, winStart, winEnd, tvFull);
 
+maybeLoadSnake(tg);
 
 /* Clean up. */
 sqlFreeResult(&sr);
 hFreeConn(&conn);
 }	/*	chainLoadItems()	*/
 
 static Color chainScoreColor(struct track *tg, void *item, struct hvGfx *hvg)
 {
 struct linkedFeatures *lf = (struct linkedFeatures *)item;
 
 return(tg->colorShades[lf->grayIx]);
 }
 
 static Color chainNoColor(struct track *tg, void *item, struct hvGfx *hvg)
 {
@@ -523,38 +543,30 @@
 tg->itemColor = chainNoColor;
 tg->color.r = 0;
 tg->color.g = 0;
 tg->color.b = 0;
 tg->altColor.r = 127;
 tg->altColor.g = 127;
 tg->altColor.b = 127;
 tg->ixColor = MG_BLACK;
 tg->ixAltColor = MG_GRAY;
 }
 
 void chainMethods(struct track *tg, struct trackDb *tdb,
 	int wordCount, char *words[])
 /* Fill in custom parts of alignment chains. */
 {
-
-boolean doSnake = cartOrTdbBoolean(cart, tg->tdb, "doSnake" , FALSE) && cfgOptionBooleanDefault("canSnake", FALSE);
-
-extern void snakeMethods(struct track *tg, struct trackDb *tdb,
-	int wordCount, char *words[]);
-if (doSnake)
-    return snakeMethods(tg, tdb, wordCount, words);
-
 struct cartOptions *chainCart;
 
 AllocVar(chainCart);
 
 boolean normScoreAvailable = chainDbNormScoreAvailable(tdb);
 
 /*	what does the cart say about coloring option	*/
 chainCart->chainColor = chainFetchColorOption(cart, tdb, FALSE);
 int scoreFilterDefault = atoi(trackDbSettingOrDefault(tdb, "scoreFilter", "0"));
 chainCart->scoreFilter = cartUsualIntClosestToHome(cart, tdb,
 	FALSE, SCORE_FILTER, scoreFilterDefault);
 
 linkedFeaturesMethods(tg);
 tg->itemColor = lfChromColor;	/*	default coloring option */
 tg->exonArrowsAlways = TRUE;