1291f2242d9627684efaa88259c1c09f5e7c1b10
braney
  Thu Apr 4 07:19:11 2019 -0700
some lollipop code leaked out on my last commit, so here's more leakage!

diff --git src/hg/hgTracks/lolly.c src/hg/hgTracks/lolly.c
index ed6ffb6..2baade1 100644
--- src/hg/hgTracks/lolly.c
+++ src/hg/hgTracks/lolly.c
@@ -1,160 +1,217 @@
-/* lolly -- load and draw lollipops */
+/* lolly -- load and draw lollys */
 
 /* Copyright (C) 2019 The Regents of the University of California 
  * See README in this or parent directory for licensing information. */
 
 #include "common.h"
 #include "obscure.h"
 #include "hgTracks.h"
 #include "bedCart.h"
 #include "bigWarn.h"
 #include "lolly.h"
 #include "limits.h"
+#include "float.h"
 
-static int trackHeight;
 
-struct lollipop
+struct lolly
 {
-struct lollipop *next;
+struct lolly *next;
 double val;
 unsigned start;
 unsigned radius;
 unsigned height;
 Color color;
 };
 
-static void lollipopDrawItems(struct track *tg, int seqStart, int seqEnd,
+static void lollyDrawItems(struct track *tg, int seqStart, int seqEnd,
         struct hvGfx *hvg, int xOff, int yOff, int width, 
         MgFont *font, Color color, enum trackVisibility vis)
-/* Draw a list of lollipop structures. */
+/* Draw a list of lolly structures. */
 {
 double scale = scaleForWindow(width, seqStart, seqEnd);
-struct lollipop *popList = tg->items, *pop;
+struct lolly *popList = tg->items, *pop;
+int trackHeight = tg->lollyCart->height;
 
 if (popList == NULL)
     return;
 
 for (pop = popList; pop; pop = pop->next)
     {
-    int sx = ((pop->start - seqStart) + .5) * scale; // x coord of center (lower region)
+    int sx = ((pop->start - seqStart) + .5) * scale + xOff; // x coord of center (lower region)
     hvGfxLine(hvg, sx, yOff + trackHeight, sx , yOff+(trackHeight - pop->height), pop->color);
     hvGfxCircle(hvg, sx, yOff + trackHeight - pop->radius - pop->height, pop->radius, pop->color, TRUE);
     }
 }
 
-void lollipopLeftLabels(struct track *tg, int seqStart, int seqEnd,
+void lollyLeftLabels(struct track *tg, int seqStart, int seqEnd,
 	struct hvGfx *hvg, int xOff, int yOff, int width, int height,
 	boolean withCenterLabels, MgFont *font, Color color,
 	enum trackVisibility vis)
 {
+int fontHeight = tl.fontHeight+1;
+int centerLabel = (height/2)-(fontHeight/2);
+hvGfxText(hvg, xOff, yOff+centerLabel, color, font, tg->shortLabel);
+char upper[1024];
+safef(upper, sizeof(upper), "%g -",   tg->lollyCart->upperLimit);
+hvGfxTextRight(hvg, xOff, yOff + 2 * 5 , width - 1, fontHeight, color,
+    font, upper);
+char lower[1024];
+safef(lower, sizeof(lower), "%g _", tg->lollyCart->lowerLimit);
+hvGfxTextRight(hvg, xOff, yOff+height-fontHeight - 2 * 5, width - 1, fontHeight,
+    color, font, lower);
 }
 
 
-static int lollipopHeight(struct track *tg, enum trackVisibility vis)
-/* calculate height of all the lollipops being displayed */
+static int lollyHeight(struct track *tg, enum trackVisibility vis)
+/* calculate height of all the lollys being displayed */
 {
+/*
 if ( tg->visibility == tvDense)
     return  tl.fontHeight;
 trackHeight = 5 * tl.fontHeight;
 return 5 * tl.fontHeight;
+*/
+return tg->lollyCart->height;
 }
 
-static void lollipopMapItem(struct track *tg, struct hvGfx *hvg, void *item, char *itemName, char *mapItemName, int start, int end,
+static void lollyMapItem(struct track *tg, struct hvGfx *hvg, void *item, char *itemName, char *mapItemName, int start, int end,
                                                                 int x, int y, int width, int height)
 {
 }
                                                                
 
 double calcVarianceFromSums(double sum, double sumSquares, bits64 n)
 /* Calculate variance. */
 {   
 double var = sumSquares - sum*sum/n;
 if (n > 1)
     var /= n-1;
 return var;
 }   
     
 double calcStdFromSums(double sum, double sumSquares, bits64 n)
 /* Calculate standard deviation. */
 {   
 return sqrt(calcVarianceFromSums(sum, sumSquares, n));
 }
 
 int cmpHeight(const void *va, const void *vb)
 {
-const struct lollipop *a = *((struct lollipop **)va);
-const struct lollipop *b = *((struct lollipop **)vb);
+const struct lolly *a = *((struct lolly **)va);
+const struct lolly *b = *((struct lolly **)vb);
 return a->height - b->height;
 }
 
-void lollipopLoadItems(struct track *tg)
+void lollyLoadItems(struct track *tg)
 {
 struct lm *lm = lmInit(0);
 struct bbiFile *bbi =  fetchBbiForTrack(tg);
 struct bigBedInterval *bb, *bbList =  bigBedIntervalQuery(bbi, chromName, winStart, winEnd, 0, lm);
 char *bedRow[bbi->fieldCount];
 char startBuf[16], endBuf[16];
-struct lollipop *popList = NULL, *pop;
-unsigned lollipopField = atoi(trackDbSetting(tg->tdb, "lollipopField"));
+struct lolly *popList = NULL, *pop;
+unsigned lollyField = 5;
+char *setting = trackDbSetting(tg->tdb, "lollyField");
+if (setting != NULL)
+    lollyField = atoi(setting);
+
 double sumData = 0.0, sumSquares = 0.0;
-//double minVal = DBL_MAX, maxVal = -DBL_MAX;
+double minVal = DBL_MAX, maxVal = -DBL_MAX;
 unsigned count = 0;
 
+int trackHeight = tg->lollyCart->height;
+                    
 for (bb = bbList; bb != NULL; bb = bb->next)
     {
     AllocVar(pop);
     slAddHead(&popList, pop);
     bigBedIntervalToRow(bb, chromName, startBuf, endBuf, bedRow, ArraySize(bedRow));
-    double val = atof(bedRow[lollipopField]);
+    double val = atof(bedRow[lollyField - 1]);
     pop->val = val;
     pop->start = atoi(bedRow[1]);
     count++;
     sumData += val;
     sumSquares += val * val;
+    if (val > maxVal)
+        maxVal = val;
+    if (val < minVal)
+        minVal = val;
+    }
+
+tg->lollyCart->upperLimit = maxVal;
+tg->lollyCart->lowerLimit = minVal;
+double range = maxVal - minVal;
+int usableHeight = trackHeight - 2 * 5 * 2; 
+for(pop = popList; pop; pop = pop->next)
+    {
+    pop->radius = 5;
+    pop->color = MG_RED;
+    pop->height = usableHeight * (pop->val  - minVal) / range + 5 * 2;
     }
 
+/*
 double average = sumData/count;
 double stdDev = calcStdFromSums(sumData, sumSquares, count);
 
 for(pop = popList; pop; pop = pop->next)
     {
     if (pop->val > average + stdDev / 5)
         {
         pop->color = MG_RED;
         pop->radius = 8;
         pop->height = 3 * tl.fontHeight;
         }
     else if (pop->val < average - stdDev / 5)
         {
         pop->color = MG_GREEN;
         pop->radius = 3;
         pop->height = 1 * tl.fontHeight;
         }
     else
         {
         pop->color = MG_GRAY;
         pop->radius = 5;
         pop->height = 2 * tl.fontHeight;
         }
         
     }
+    */
 slSort(&popList, cmpHeight);
 tg->items = popList;
 }
 
-void lollipopMethods(struct track *track, struct trackDb *tdb, 
+static struct lollyCartOptions *lollyCartOptionsNew(struct cart *cart, struct trackDb *tdb, 
+                                int wordCount, char *words[])
+{
+struct lollyCartOptions *lollyCart;
+AllocVar(lollyCart);
+
+int maxHeightPixels;
+int minHeightPixels;
+int defaultHeight;  /*  pixels per item */
+int settingsDefault;
+cartTdbFetchMinMaxPixels(cart, tdb, MIN_HEIGHT_PER, atoi(DEFAULT_HEIGHT_PER), atoi(DEFAULT_HEIGHT_PER),
+                                &minHeightPixels, &maxHeightPixels, &settingsDefault, &defaultHeight);
+lollyCart->height = defaultHeight;
+
+return lollyCart;
+}
+
+void lollyMethods(struct track *track, struct trackDb *tdb, 
                                 int wordCount, char *words[])
-/* Interact track type methods */
+/* bigLolly track type methods */
 {
+struct lollyCartOptions *lollyCart = lollyCartOptionsNew(cart, tdb, wordCount, words);
 char *ourWords[2];
 ourWords[0] = "bigBed";
 ourWords[1] = "4";
 bigBedMethods(track, tdb,2,ourWords);
 if (tdb->visibility == tvDense)
     return;
-track->loadItems = lollipopLoadItems;
-track->drawItems = lollipopDrawItems;
-track->totalHeight = lollipopHeight; 
-track->drawLeftLabels = lollipopLeftLabels;
-track->mapItem = lollipopMapItem;
+track->loadItems = lollyLoadItems;
+track->drawItems = lollyDrawItems;
+track->totalHeight = lollyHeight; 
+track->drawLeftLabels = lollyLeftLabels;
+track->mapItem = lollyMapItem;
+track->lollyCart = lollyCart;
 }