faafcf1c5f1b1da28a628d6e9aa7ab9d3ee455a8
braney
  Fri Apr 28 12:13:01 2023 -0700
fix pack mode

diff --git src/hg/hgTracks/snake.c src/hg/hgTracks/snake.c
index 215f29e..76337eb 100644
--- src/hg/hgTracks/snake.c
+++ src/hg/hgTracks/snake.c
@@ -16,40 +16,57 @@
 #include "chainCart.h"
 #include "errCatch.h"
 #include "twoBit.h"
 #include "bigWarn.h"
 #include <pthread.h>
 #include "trackHub.h"
 #include "limits.h"
 #include "snakeUi.h"
 #include "bits.h"
 #include "trix.h"
 #include "chromAlias.h"
 
 #include "bigPsl.h"
 #include "snake.h"
 
+typedef int (*compareFunction )(const void *elem1,  const void *elem2);
+
 static int snakeFeatureCmpScore(const void *va, const void *vb)
 /* sort by score of the alignment. */
 {
 const struct snakeFeature *a = *((struct snakeFeature **)va);
 const struct snakeFeature *b = *((struct snakeFeature **)vb);
 int diff = b->score - a->score;
 
 return diff;
 }
 
+static int snakeFeatureCmpTStart(const void *va, const void *vb)
+/* sort by start position on the target sequence */
+{
+const struct snakeFeature *a = *((struct snakeFeature **)va);
+const struct snakeFeature *b = *((struct snakeFeature **)vb);
+int diff = a->start - b->start;
+
+if (diff == 0)
+    {
+    diff = a->qStart - b->qStart;
+    }
+
+return diff;
+}
+
 static int snakeFeatureCmpQStart(const void *va, const void *vb)
 /* sort by start position on the query sequence */
 {
 const struct snakeFeature *a = *((struct snakeFeature **)va);
 const struct snakeFeature *b = *((struct snakeFeature **)vb);
 int diff = a->qStart - b->qStart;
 
 if (diff == 0)
     {
     diff = a->start - b->start;
     }
 
 return diff;
 }
 
@@ -1124,133 +1141,139 @@
     else
 	lastX = ex;
     lastS = s;
     lastE = e;
     lastLevel = sf->level;
     lastQEnd = qe;
     }
 }
 
 struct cartOptions
     {
     enum chainColorEnum chainColor; /*  ChromColors, ScoreColors, NoColors */
     int scoreFilter ; /* filter chains by score if > 0 */
     };
 
-static void fixItems(struct linkedFeatures *lf)
+static void fixItems(struct linkedFeatures *lf, compareFunction compare)
 // put all chain blocks from a single query chromosome into one
 // linkedFeatures structure
 {
 struct linkedFeatures *firstLf, *next;
 struct snakeFeature  *sf,  *nextSf;
 
 firstLf = lf;
 for (;lf; lf = next)
     {
     next = lf->next;
     if (!sameString(firstLf->name, lf->name) && (lf->components != NULL))
 	{
-	slSort(&firstLf->components, snakeFeatureCmpQStart);
+	slSort(&firstLf->components, compare);
         firstLf->next = lf;
 	firstLf = lf;
 	}
     for (sf =  (struct snakeFeature *)lf->components; sf != NULL; sf = nextSf)
 	{
 	sf->qName = lf->name;
 	sf->orientation = lf->orientation;
         sf->score = lf->score;
 	nextSf = sf->next;
 	if (firstLf != lf)
 	    {
 	    lf->components = NULL;
 	    slAddHead(&firstLf->components, sf);
 	    }
 	}
     }
 
 if (firstLf != NULL)
     {
-    slSort(&firstLf->components, snakeFeatureCmpQStart);
+    slSort(&firstLf->components, compare);
     firstLf->next = 0;
     }
 }
 
 
 void snakeDrawLeftLabels()
 {
 }
 
 static void makeSnakeFeatures(struct linkedFeatures *lf)
 /* allocate an info structure for every block in the alignment. */
 {
 for(; lf; lf = lf->next)
     {
     struct simpleFeature *sf = lf->components;
     struct snakeFeature *sfList = NULL;
 
     for(;sf; sf = sf->next)
         {
         struct snakeFeature *this;
 
         AllocVar(this);
         *(struct simpleFeature *)this = *sf;
 	this->orientation = lf->orientation;
         slAddHead(&sfList, this);
         }
     lf->components = (struct simpleFeature *)sfList;
     }
 }
 
-static void makeSingleCoverage(struct linkedFeatures *lf)
+static void makeSingleCoverage(struct linkedFeatures *lf, compareFunction compare)
 /* Because snakes are a display of O+O of the query sequence projected onto the reference sequence, 
  * we need to only have one copy of each piece of the query sequence. */
 {
 for(; lf; lf = lf->next)   // for each query sequence
     {
     slSort(&lf->components, snakeFeatureCmpScore); // we want to choose the higher scoring alignements
     Bits *qBits = bitAlloc(lf->qSize); // the bit array we use to keep track if we've seen this query sequence
     struct simpleFeature *sf = lf->components;
     struct simpleFeature *prevSf = NULL;
 
     for(; sf ; sf = sf->next)
         {
         // have we seen this query range?
         if (bitCountRange(qBits, sf->qStart, sf->qEnd - sf->qStart))
             {
             // if we've seen this query sequence, then delete it
             if (prevSf == NULL)
                 lf->components = sf->next;
             else
                 prevSf->next = sf->next;
             }
         else
             {
             bitSetRange(qBits, sf->qStart, sf->qEnd - sf->qStart);
             prevSf = sf;
             }
         }
 
-    slSort(&lf->components, snakeFeatureCmpQStart);
+    slSort(&lf->components, compare);
     }
 }
 
 void maybeLoadSnake(struct track *track)
 /* check to see if we're doing snakes and if so load the correct methods. */
 {
 boolean doSnake = cartOrTdbBoolean(cart, track->tdb, "doSnake", FALSE);
 if (doSnake)
     {
+    compareFunction compare;
+    if (track->visibility == tvFull)
+        compare = snakeFeatureCmpQStart;
+    else
+        // we don't care about the order on query
+        compare = snakeFeatureCmpTStart;
+
     track->drawLeftLabels = snakeDrawLeftLabels;
     track->itemHeight = snakeItemHeight;
     track->totalHeight = snakeHeight;
     track->drawItemAt = snakeDrawAt;
     track->drawItems = snakeDraw;
 
     slSort(&track->items, linkedFeaturesCmpName);
     makeSnakeFeatures(track->items);
-    fixItems(track->items);
-    makeSingleCoverage(track->items);
-    track->visibility = track->limitedVis = tvFull;
+    fixItems(track->items, compare);
+    makeSingleCoverage(track->items, compare);
     track->canPack = FALSE;
     }
 }