a7cdd40a9c37d4d90c7aa9766c5248c0cb3f259a
braney
  Wed May 21 17:22:17 2025 -0700
add bedMethyl type for custom and native tracks

diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c
index 55dfafa301c..a5431653279 100644
--- src/hg/hgTracks/simpleTracks.c
+++ src/hg/hgTracks/simpleTracks.c
@@ -137,30 +137,31 @@
 #include "rnaPLFoldTrack.h"
 #endif /* LOWELAB */
 #ifdef LOWELAB_WIKI
 #include "wiki.h"
 #endif /* LOWELAB_WIKI */
 
 #include "trackVersion.h"
 #include "genbank.h"
 #include "bedTabix.h"
 #include "knetUdc.h"
 #include "trackHub.h"
 #include "hubConnect.h"
 #include "bigWarn.h"
 #include "quickLift.h"
 #include "liftOver.h"
+#include "bedMethyl.h"
 
 #define CHROM_COLORS 26
 
 /* Declare our color gradients and the the number of colors in them */
 Color shadesOfGreen[EXPR_DATA_SHADES];
 Color shadesOfRed[EXPR_DATA_SHADES];
 Color shadesOfBlue[EXPR_DATA_SHADES];
 Color shadesOfYellow[EXPR_DATA_SHADES];
 Color shadesOfGreenOnWhite[EXPR_DATA_SHADES];
 Color shadesOfRedOnWhite[EXPR_DATA_SHADES];
 Color shadesOfBlueOnWhite[EXPR_DATA_SHADES];
 Color shadesOfYellowOnWhite[EXPR_DATA_SHADES];
 Color shadesOfRedOnYellow[EXPR_DATA_SHADES];
 Color shadesOfBlueOnYellow[EXPR_DATA_SHADES];
 Color orangeColor = 0;
@@ -12089,30 +12090,52 @@
    int t = f + 1;
    if (vis != tvDense)
        {
        f = f*2;
        t = t*2;
        }
    return tgFixedTotalHeightOptionalOverflow(tg,vis, t, f, FALSE);
 }
 
 void freePgSnp(struct track *tg)
 /* Free pgSnp items. */
 {
 pgSnpFreeList(((struct pgSnp **)(&tg->items)));
 }
 
+void loadBedMethyl(struct track *tg)
+/* Load up bedMethyl type tracks */
+{
+struct customTrack *ct = tg->customPt;
+char *table = tg->table;
+struct sqlConnection *conn;
+if (ct == NULL)
+    conn = hAllocConn(database);
+else
+    {
+    conn = hAllocConn(CUSTOM_TRASH);
+    table = ct->dbTableName;
+    }
+struct dyString *query = sqlDyStringCreate("select * from %s where ", table);
+hAddBinToQuery(winStart, winEnd, query);
+sqlDyStringPrintf(query, "chrom = '%s' and chromStart < %d and chromEnd > %d",
+	       chromName, winEnd, winStart);
+tg->items = bedMethylLoadByQuery(conn, query->string);
+
+hFreeConn(&conn);
+}
+
 void loadPgSnp(struct track *tg)
 /* Load up pgSnp (personal genome SNP) type tracks */
 {
 struct customTrack *ct = tg->customPt;
 char *table = tg->table;
 struct sqlConnection *conn;
 if (ct == NULL)
     conn = hAllocConn(database);
 else
     {
     conn = hAllocConn(CUSTOM_TRASH);
     table = ct->dbTableName;
     }
 struct dyString *query = sqlDyStringCreate("select * from %s where ", table);
 hAddBinToQuery(winStart, winEnd, query);
@@ -12159,44 +12182,53 @@
 		     boolean withCenterLabels, MgFont *font, Color color,
 		     enum trackVisibility vis)
 /* pgSnp draws its own left labels when it draws the item in pack or full mode.
  * We don't want the default left labels when in full mode because they can overlap
  * with the item-drawing labels, but we do still need dense mode left labels. */
 {
 if (vis == tvDense)
     {
     if (isCenterLabelIncluded(tg))
 	yOff += mgFontLineHeight(font);
     hvGfxTextRight(hvg, leftLabelX, yOff, leftLabelWidth-1, tg->lineHeight,
 		   color, font, tg->shortLabel);
     }
 }
 
+void bedMethylMethods (struct track *tg)
+/* bedMethyl track methods */
+{
+bedMethods(tg);
+tg->loadItems = loadBedMethyl;
+tg->canPack = TRUE;
+}
+
 void pgSnpMethods (struct track *tg)
 /* Personal Genome SNPs: show two alleles with stacked color bars for base alleles and
  * (if available) allele counts in mouseover. */
 {
 bedMethods(tg);
 tg->loadItems = loadPgSnp;
 tg->freeItems = freePgSnp;
 tg->totalHeight = pgSnpHeight;
 tg->itemName = pgSnpName;
 tg->drawItemAt = pgSnpDrawAt;
 tg->mapItem = pgSnpMapItem;
 tg->nextItemButtonable = TRUE;
 tg->nextPrevItem = linkedFeaturesLabelNextPrevItem;
 tg->drawLeftLabels = pgSnpLeftLabels;
+tg->canPack = TRUE;
 }
 
 void loadBlatz(struct track *tg)
 {
 enum trackVisibility vis = tg->visibility;
 loadXenoPsl(tg);
 if (vis != tvDense)
     {
     lookupProteinNames(tg);
     }
 vis = limitVisibility(tg);
 }
 
 void loadBlast(struct track *tg)
 {
@@ -13285,30 +13317,37 @@
 if (ct != NULL && ct->fieldCount >= (9+2)) /* at least bed9 */
     {
     linkedFeaturesMethods(tg);
     tg->loadItems = loadBedDetail;
     }
 else  /* when in doubt set up as simple bed */
     {
     bedMethods(tg);
     tg->loadItems = loadBedDetailSimple;
     }
 tg->nextItemButtonable = TRUE;
 tg->customPt = ct;
 tg->canPack = TRUE;
 }
 
+void bedMethylCtMethods (struct track *tg)
+/* Load pgSnp track from custom tracks */
+{
+bedMethylMethods(tg);
+tg->canPack = TRUE;
+}
+
 void pgSnpCtMethods (struct track *tg)
 /* Load pgSnp track from custom tracks */
 {
 /* start with the pgSnp methods */
 pgSnpMethods(tg);
 tg->mapItemName = pgSnpCtMapItemName;
 tg->canPack = TRUE;
 }
 
 void bedDetailMethods (struct track *tg)
 /* Load bed detail track as bed 4-12 */
 {
 struct trackDb *tdb = tg->tdb;
 char *words[3];
 int size, cnt = chopLine(cloneString(tdb->type), words);
@@ -15035,30 +15074,34 @@
     {
     bamWigMethods(track, tdb, wordCount, words);
     }
 else if (sameWord(type, "gvf"))
     {
     gvfMethods(track);
     }
 else if (sameWord(type, "barChart"))
     {
     barChartMethods(track);
     }
 else if (sameWord(type, "interact"))
     {
     interactMethods(track);
     }
+else if (sameWord(type, "bedMethyl"))
+    {
+    bedMethylMethods(track);
+    }
 /* add handlers for wildcard */
 if (startsWith("peptideAtlas", track->track))
     peptideAtlasMethods(track);
 else if (startsWith("gtexGene", track->track))
     gtexGeneMethods(track);
 else if (startsWith("rnaStruct", track->track))
     rnaSecStrMethods(track);
 #endif /* GBROWSE */
 }
 
 static void compositeLoad(struct track *track)
 /* Load all subtracks */
 {
 struct track *subtrack;
 long thisTime = 0, lastTime = 0;