75b9f337975beb5a9eaec5ff00e48cb878591fd2
braney
  Fri Aug 7 12:07:35 2026 -0700
bigLolly: reserve top margin from the largest lolly actually drawn, refs #38031

A track that sets lollySizeField scales each radius by the track height, so a
lolly can end up bigger than lollyMaxSize.  The margins were reserved from
lollyMaxSize alone, so once the drawn radius passed it the top row of circles
ran off the top of the row and came out flat.  Take the larger of the two, which
leaves every current picture unchanged since today's radii are all below
lollyMaxSize.  The same margin positions the y-axis gridlines and the upper and
lower value labels, so all three move together and the axis still lines up with
the circles.

diff --git src/hg/hgTracks/lollyTrack.c src/hg/hgTracks/lollyTrack.c
index a29c88174ba..acdf893df89 100644
--- src/hg/hgTracks/lollyTrack.c
+++ src/hg/hgTracks/lollyTrack.c
@@ -3,45 +3,64 @@
 /* Copyright (C) 2019 The Regents of the University of California 
  * See kent/LICENSE or http://genome.ucsc.edu/license/ 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"
 #include "bigBedFilter.h"
 #include "asParse.h"
 #include "quickLift.h"
 
-#define LOLLY_DIAMETER    2 * (lollyCart->radius + 2)
+#define LOLLY_DIAMETER    2 * (lollyMaxRadius(tg) + 2)
 
 struct lolly
 {
 struct lolly *next;
 char *name;       /* the mouseover name */
 double val;       /* value in the data file */   
 unsigned start;   /* genomic start address */
 unsigned end;     /* genomic end address */
 unsigned radius;  /* radius of the top of the lolly */
 unsigned height;  /* height of the lolly */
 Color color;      /* color of the lolly */
 char *mouseOver;
 };
 
+static unsigned lollyMaxRadius(struct track *tg)
+/* Return the radius of the largest lolly that will be drawn.  A track that sets
+ * lollySizeField scales each radius by the track height at load time, so a lolly
+ * can be bigger than lollyMaxSize.  Reserving margins from lollyMaxSize alone
+ * clips the top row once that happens. */
+{
+unsigned maxRadius = tg->lollyCart->radius;
+struct lolly *pop;
+
+for(pop = tg->items; pop; pop = pop->next)
+    {
+    // a radius of -1 means the lolly takes the default, which is the floor above
+    if ((pop->radius != -1) && (pop->radius > maxRadius))
+        maxRadius = pop->radius;
+    }
+
+return maxRadius;
+}
+
 static unsigned getLollyColor( struct hvGfx *hvg, unsigned color)
 /* Get the device color from our internal definition. */
 {
 struct rgbColor itemRgb;
 itemRgb.r = (color & 0xff0000) >> 16;
 itemRgb.g = (color & 0xff00) >> 8;
 itemRgb.b = color & 0xff;
 return  hvGfxFindColorIx(hvg, itemRgb.r, itemRgb.g, itemRgb.b);
 }
 
 // structure to capture yLabels
 struct yLabel
 {
 struct yLabel *next;
 unsigned y;