f80b3826a921197488ece1440ff08038ec9e572d
braney
  Mon Jun 29 12:28:07 2026 -0700
hgConvert/hgTracks: add option to hide target default tracks on QuickLift convert

Adds a "Hide all default tracks on the target" checkbox (on by default) to
the Convert page when QuickLift is enabled. When set, the QuickLift link
appends hideTracks=on, and hgTracks now leaves QuickLifted tracks visible
when hiding the target assembly's default tracks.

refs #37815

diff --git src/hg/hgConvert/hgConvert.c src/hg/hgConvert/hgConvert.c
index 8f0fce284aa..55eacd11b4c 100644
--- src/hg/hgConvert/hgConvert.c
+++ src/hg/hgConvert/hgConvert.c
@@ -60,35 +60,37 @@
     }
 
 struct dbDb *toDb =  genarkLiftOverDb(name);
 if (toDb == NULL)
     errAbort("Can't find %s in matchingDb", name);
 return toDb;
 }
 
 static void askForDestination(struct liftOverChain *liftOver, char *fromPos,
 	struct dbDb *fromDb, struct dbDb *toDb)
 /* set up page for entering data */
 {
 struct dbDb *dbList;
 boolean askAboutQuickLift = FALSE;
 boolean quickLift = FALSE;
+boolean hideOtherTracks = TRUE;
 
 if (quickLiftEnabled(cart))
     {
     askAboutQuickLift = TRUE;
     quickLift = cartUsualBoolean(cart, "doQuickLift", FALSE);
+    hideOtherTracks = cartUsualBoolean(cart, "hideTracksOnConvert", TRUE);
     }
 
 cartWebStart(cart, database, "Convert %s to New Assembly", fromPos);
 
 /* Include autocomplete libraries */
 jsIncludeAutoCompleteLibs();
 
 /* create HTML form */
 puts("<FORM ACTION=\"../cgi-bin/hgConvert\" NAME=\"mainForm\">\n");
 cartSaveSession(cart);
 
 cgiParagraph(
     "This tool converts the current genome browser position to the corresponding "
     "region in another assembly or species using genome sequence alignments. "
     "Select a target assembly below and click Submit to jump to the matching region. "
@@ -135,30 +137,51 @@
 hPrintf("<div class='currentSelection' id='toGenomeLabel'>%s</div>\n", selectedLabel);
 /* Assembly dropdown (updates based on genome selection) */
 puts("<div class='fieldRow'>\n");
 puts("<span class='fieldLabel'>Assembly:</span>\n");
 dbList = hGetLiftOverToDatabases(liftOver->fromDb);
 printAllAssemblyListHtmlParm(liftOver->toDb, dbList, "hglft_toDbSelect", TRUE, "change", onChangeToOrg);
 puts("</div>\n");
 
 /* QuickLift option */
 if (askAboutQuickLift)
     {
     puts("<div class='fieldRow' style='margin-top: 15px;'>\n");
     cgiMakeCheckBoxWithId("doQuickLift", quickLift, "doQuickLift");
     puts(" <label for='doQuickLift' title='Display tracks from the source assembly mapped onto the target assembly'>QuickLift tracks</label>\n");
     puts("</div>\n");
+
+    puts("<div class='fieldRow' id='hideTracksOnConvertRow' style='margin-top: 8px;'>\n");
+    cgiMakeCheckBoxWithId("hideTracksOnConvert", hideOtherTracks, "hideTracksOnConvert");
+    puts(" <label for='hideTracksOnConvert' title='Hide all of the target assembly default tracks, showing only the QuickLifted tracks'>Hide all default tracks on the target</label>\n");
+    puts("</div>\n");
+
+    /* The hide option only applies when QuickLift is on; gray it out otherwise. */
+    jsInline(
+        "function hgcUpdateHideTracks() {\n"
+        "    let ql = document.getElementById('doQuickLift');\n"
+        "    let hideBox = document.getElementById('hideTracksOnConvert');\n"
+        "    let hideRow = document.getElementById('hideTracksOnConvertRow');\n"
+        "    if (!ql || !hideBox || !hideRow) return;\n"
+        "    hideBox.disabled = !ql.checked;\n"
+        "    hideRow.style.opacity = ql.checked ? '1' : '0.5';\n"
+        "}\n"
+        "document.addEventListener('DOMContentLoaded', function() {\n"
+        "    let ql = document.getElementById('doQuickLift');\n"
+        "    if (ql) ql.addEventListener('change', hgcUpdateHideTracks);\n"
+        "    hgcUpdateHideTracks();\n"
+        "});\n");
     }
 
 puts("</div>\n");  /* end destination section */
 puts("</div>\n");  /* end grid */
 
 /* Submit button centered below */
 puts("<div style='text-align: center; margin-top: 20px;'>\n");
 cgiMakeButton(HGLFT_DO_CONVERT, "Submit");
 puts("</div>\n");
 
 /* JavaScript initialization for autocomplete with liftOver filtering */
 jsInlineF(
     "let validTargets = new Set();\n"
     "\n"
     "fetch('../cgi-bin/hubApi/liftOver/listExisting?fromGenome=%s')\n"
@@ -247,30 +270,36 @@
     , liftOver->fromDb
     , HGLFT_TOORG_VAR
     , HGLFT_TODB_VAR
     , searchBarId, searchBarId, searchBarId, searchBarId
     , searchBarId, searchBarId, searchBarId
 );
 
 puts("</FORM>\n");
 
 webNewSection("Notes");
 cgiParagraph(
     "<B>QuickLift tracks:</B> When enabled, QuickLift displays tracks from "
     "the source assembly mapped onto the target assembly, allowing you to view "
     "your current tracks in the context of the new genome. For more information, see the "
     "<A HREF=\"../goldenPath/help/quickLift.html\">QuickLift documentation</A>.");
+cgiParagraph(
+    "<B>Hide all default tracks on the target:</B> When QuickLift is enabled, this "
+    "option (on by default) hides the target assembly's default tracks so that only "
+    "your QuickLifted tracks are shown, letting you focus on the tracks carried over "
+    "from the source assembly. Uncheck it to display the target assembly's default "
+    "tracks alongside the QuickLifted tracks.");
 cgiParagraph(
     "If your desired target assembly is not available, you can search for it "
     "and request it on our "
     "<A HREF=\"../assemblySearch.html\">Assembly Search</A> page.");
 
 cartWebEnd();
 }
 
 static double scoreLiftOverChain(struct liftOverChain *chain,
     char *fromOrg, char *fromDb, char *toOrg, char *toDb, struct hash *dbRank )
 /* Score the chain in terms of best match for cart settings */
 {
 double score = 0;
 
 char *chainFromOrg = hOrganism(chain->fromDb);
@@ -613,30 +642,32 @@
     errAbort("Unable to find a chain file from %s to %s - please contact support", fromDb->name, toDb->name);
 
 fileName = hReplaceGbdbMustDownload(fileName);
 char *chrom;
 int start, end;
 int origSize;
 struct chain *chainList, *chain;
 struct dyString *visDy = NULL;
 
 if (!hgParseChromRange(database, fromPos, &chrom, &start, &end))
     errAbort("position %s is not in chrom:start-end format", fromPos);
 origSize = end - start;
 
 boolean doQuickLift = cartUsualBoolean(cart, "doQuickLift", FALSE);
 cartRemove(cart, "doQuickLift");
+boolean hideOtherTracks = cartUsualBoolean(cart, "hideTracksOnConvert", TRUE);
+cartRemove(cart, "hideTracksOnConvert");
 
 unsigned quickChain = 0;
 unsigned quickHub = 0;
 struct trackDb *badList = NULL;
 
 if (doQuickLift)
     {
     quickChain = quickLiftGetChainId(cart, trackHubSkipHubName(fromDb->name), trackHubSkipHubName(toDb->name));
 
     if (quickChain == 0)
         errAbort("can't find quickChain from %s to %s", fromDb->name, toDb->name);
 
     visDy = newDyString(1024);
     char *newHub = trackHubBuild(fromDb->name, cart, visDy, &badList);
     char *error = NULL;
@@ -668,32 +699,33 @@
         /* Check if the toDb database exists and if the chromosome
            sequence file (of the hgConvert result) exists in the location
            specified in chromInfo for the toDb. */
 
         boolean chromSeqExists = (sqlDatabaseExists(toDb->name) &&
 				  chromSeqFileExists(toDb->name, chain->qName));
         /* Check if the toDb has active set to 1 in dbDb if the toDb
            database exists.
            If these conditions are met then print position link to
            browser for toDb, otherwise just print position without link. */
         boolean startedAnchor = FALSE;
         visDy = newDyString(20);
         if ((hDbIsActive(toDb->name) && chromSeqExists) || startsWith("hub:",toDb->nibPath) || sameString(toDb->nibPath, "genark"))
             {
             if (quickChain)
-                printf("<A HREF=\"%s?db=%s&position=%s:%d-%d&quickLift.%d.%s=%d\">",
-                   hgTracksName(),  toDb->name,  chain->qName, qStart+1, qEnd, quickHub, toDb->name, quickChain);
+                printf("<A HREF=\"%s?db=%s&position=%s:%d-%d&quickLift.%d.%s=%d%s\">",
+                   hgTracksName(),  toDb->name,  chain->qName, qStart+1, qEnd, quickHub, toDb->name, quickChain,
+                   hideOtherTracks ? "&hideTracks=on" : "");
             else
                 printf("<A HREF=\"%s?db=%s&position=%s:%d-%d\">",
 		   hgTracksName(), toDb->name, chain->qName, qStart+1, qEnd);
             startedAnchor = TRUE;
             }
 	printf("%s:%d-%d",  chain->qName, qStart+1, qEnd);
         if (startedAnchor)
 	    printf("</A>");
 	printf(" (%3.1f%% of bases, %3.1f%% of span)<BR>\n",
 	    100.0 * blockSize/origSize,
 	    100.0 * (chain->tEnd - chain->tStart) / origSize);
 #ifdef NTONOW
         if (doSegments)
             drawSegments(fromDb->name, toDb->name, chain);
         break;