f63a718960b6a66276d579e7cd3fbb107f2cfd78
tdreszer
  Tue Nov 16 16:37:13 2010 -0800
Removed obsolete ifdef for SUBTRACKS_HAVE_VIS. Streamlined some composite vis code. Added support for remote tracks being rendered by AJAX callback.  Currently ifdefed out.
diff --git src/hg/hgTracks/hgTracks.c src/hg/hgTracks/hgTracks.c
index 5077694..7267911 100644
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@ -257,45 +257,43 @@
                         }
                     else
                         cartSetString(cart, parentTdb->track,
                                     changeVis == tvHide ? "hide" : "show");
                     }
                 else // Not super  child
                     {
                     if (changeVis == tdb->visibility)
                         /* remove if setting to default vis */
                         cartRemove(cart, track->track);
                     else
                         cartSetString(cart, track->track, hStringFromTv(changeVis));
                     track->visibility = changeVis;
                     }
 
-                #ifdef SUBTRACKS_HAVE_VIS
                 // Whether super child or not, if its a composite, then handle the children
                 if (tdbIsComposite(tdb))
                     {
                     struct track *subtrack;
                     for(subtrack=track->subtracks;subtrack!=NULL;subtrack=subtrack->next)
                         {
                         if (changeVis == tvHide)
                             cartRemove(cart, subtrack->track); // Since subtrack level vis is an override, simply remove it to hide it
                         else
                             cartSetString(cart, subtrack->track, hStringFromTv(changeVis));
                         subtrack->visibility = changeVis;
                         }
                     }
-                #endif///def SUBTRACKS_HAVE_VIS
                 }
             }
         }
     }
 slSort(&groupList, gCmpPriority);
 }
 
 int trackOffsetX()
 /* Return x offset where track display proper begins. */
 {
 int x = gfxBorder;
 if (withLeftLabels)
     x += tl.leftLabelWidth + gfxBorder;
 return x;
 }
@@ -359,34 +357,68 @@
 char buf[2048];
 if(chromName == NULL)
     safef(buf, sizeof(buf), "%s?%s=%u&g=%s", hgTrackUiName(), cartSessionVarName(), cartSessionId(cart), encodedMapName);
 else
     safef(buf, sizeof(buf), "%s?%s=%u&c=%s&g=%s", hgTrackUiName(), cartSessionVarName(), cartSessionId(cart), chromName, encodedMapName);
 freeMem(encodedMapName);
 return(cloneString(buf));
 }
 
 void smallBreak()
 /* Draw small horizontal break */
 {
 hPrintf("<FONT SIZE=1><BR></FONT>\n");
 }
 
+#ifdef REMOTE_TRACK_AJAX_CALLBACK
+static boolean trackUsesRemoteData(struct track *track)
+/* returns TRUE is this track has a remote datasource */
+{
+if (!IS_KNOWN(track->remoteDataSource))
+    {
+    SET_TO_NO(track->remoteDataSource);
+    //if (track->bbiFile != NULL)   // FIXME: Chicken or the egg.  bigWig/bigBed "bbiFile" filled in by loadItems, but we don't want to load items.
+    //    {
+    //    if (!startsWith("/gbdb/",track->bbiFile->fileName))
+    //        SET_TO_YES(track->remoteDataSource);
+    //    }
+    if (startsWithWord("bigWig",track->tdb->type) || startsWithWord("bigBed",track->tdb->type))
+        {
+        SET_TO_YES(track->remoteDataSource);
+        }
+    else if (startsWithWord("bam",track->tdb->type))
+        {
+        SET_TO_YES(track->remoteDataSource);
+        }
+    }
+return IS_YES(track->remoteDataSource);
+}
+
+boolean trackShouldUseAjaxRetrieval(struct track *track)
+/* Tracks with remote data sources should berendered via an ajax callback */
+{
+return (theImgBox && !trackImgOnly && trackUsesRemoteData(track));
+}
+#endif///def REMOTE_TRACK_AJAX_CALLBACK
+
 static int trackPlusLabelHeight(struct track *track, int fontHeight)
 /* Return the sum of heights of items in this track (or subtrack as it may be)
  * and the center label(s) above the items (if any). */
 {
+if (trackShouldUseAjaxRetrieval(track))
+    return REMOTE_TRACK_HEIGHT;
+
 int y = track->totalHeight(track, limitVisibility(track));
 if (isCenterLabelIncluded(track))
     y += fontHeight;
 if (tdbIsComposite(track->tdb))
     {
     struct track *subtrack;
     for (subtrack = track->subtracks;  subtrack != NULL; subtrack = subtrack->next)
         {
         if (isSubtrackVisible(subtrack) &&  isCenterLabelIncluded(subtrack))
             y += fontHeight;
         }
     }
 return y;
 }
 
@@ -1548,42 +1580,40 @@
     {
     scaleBases = 2 * pow(10, numFigs);
     scaleBasesTextNum = 2 * pow(10, numFigs % 3);
     }
 if ((numFigs >= 3) && (numFigs < 6))
     baseWord = "kb";
 else if ((numFigs >= 6) && (numFigs < 9))
     baseWord = "Mb";
 safef(scaleText, scaleTextSize, "%d %s", scaleBasesTextNum, baseWord);
 return scaleBases;
 }
 
 enum trackVisibility limitedVisFromComposite(struct track *subtrack)
 /* returns the subtrack visibility which may be limited by composite with multi-view dropdowns. */
 {
-enum trackVisibility vis = subtrack->limitedVisSet ? tvMin(subtrack->visibility,subtrack->limitedVis) : subtrack->visibility;
+assert(tdbIsCompositeChild(subtrack->tdb));
 if(tdbIsCompositeChild(subtrack->tdb))
     {
     if (!subtrack->limitedVisSet)
         {
         subtrack->visibility = tdbVisLimitedByAncestors(cart, subtrack->tdb, TRUE, TRUE);
         limitVisibility(subtrack);
-        return vis;
         }
-    return subtrack->limitedVis;
     }
-return vis;
+return subtrack->limitedVis;
 }
 
 static int makeRulerZoomBoxes(struct hvGfx *hvg, struct cart *cart, int winStart,int winEnd,
 	int insideWidth,int seqBaseCount,int rulerClickY,int rulerClickHeight)
 /* Make hit boxes that will zoom program around ruler. */
 {
 int boxes = 30;
 int winWidth = winEnd - winStart;
 int newWinWidth = winWidth;
 int i, ws, we = 0, ps, pe = 0;
 int mid, ns, ne;
 double wScale = (double)winWidth/boxes;
 double pScale = (double)insideWidth/boxes;
 char message[32];
 char *zoomType = cartCgiUsualString(cart, RULER_BASE_ZOOM_VAR, ZOOM_3X);
@@ -1940,111 +1970,82 @@
     yAfterBases = yAfterRuler;
     pixHeight += basePositionHeight;
     if (rulerCds)
         {
         yAfterRuler += rulerTranslationHeight;
         pixHeight += rulerTranslationHeight;
         }
     }
 
 boolean safeHeight = TRUE;
 /* firefox on Linux worked almost up to 34,000 at the default 620 width */
 #define maxSafeHeight   32000
 /* Hash tracks/subtracks, limit visibility and calculate total image height: */
 for (track = trackList; track != NULL; track = track->next)
     {
+    if(tdbIsCompositeChild(track->tdb)) // When single track is requested via AJAX, it could be a subtrack
+        limitedVisFromComposite(track);
+    else
         limitVisibility(track);
+
     if (!safeHeight)
         {
         track->limitedVis = tvHide;
         track->limitedVisSet = TRUE;
         continue;
         }
-#ifndef SUBTRACKS_HAVE_VIS
-    if (track->limitedVis != tvHide)
-#endif///ndef SUBTRACKS_HAVE_VIS
-        {
+
         if (tdbIsComposite(track->tdb))
             {
             struct track *subtrack;
             for (subtrack = track->subtracks; subtrack != NULL;
                          subtrack = subtrack->next)
                 {
                 if (!isSubtrackVisible(subtrack))
                     continue;
 
-                // If the composite track has "view" based drop downs, set visibility based upon those
-                enum trackVisibility vis = limitedVisFromComposite(subtrack);
-                if(subtrack->visibility != vis)
-                    {
-                    subtrack->visibility = vis;
-                    if (subtrack->limitedVisSet)
-                        {
-                        subtrack->limitedVis = tvMin(vis, subtrack->limitedVis);
-                        }
-                    else
-                        {
-                        subtrack->limitedVis = tvMin(vis,subtrack->visibility);
-                        subtrack->limitedVisSet = (subtrack->limitedVis != tvHide && subtrack->visibility != subtrack->limitedVis);
-                        }
-                    }
-                if (!subtrack->limitedVisSet && track->limitedVisSet)
-                    {
-                    subtrack->visibility = track->visibility;
-                    subtrack->limitedVis = track->limitedVis;
-                    subtrack->limitedVisSet = track->limitedVisSet;
-                    }
+            // subtrack vis can be explicit or inherited from composite/view.  Then it could be limited because of pixel height
+            limitedVisFromComposite(subtrack);
+            assert(subtrack->limitedVisSet);
 
-                #ifdef SUBTRACKS_HAVE_VIS
                 if (subtrack->limitedVis != tvHide)
-                #endif///def SUBTRACKS_HAVE_VIS
                     {
                     subtrack->hasUi = track->hasUi;
                     flatTracksAdd(&flatTracks,subtrack,cart);
                     }
                 }
             }
-        else
-            #ifdef SUBTRACKS_HAVE_VIS
-            if (track->limitedVis != tvHide)
-            #endif///def SUBTRACKS_HAVE_VIS
+    else if (track->limitedVis != tvHide)
                 flatTracksAdd(&flatTracks,track,cart);
-        if (maxSafeHeight < (pixHeight+trackPlusLabelHeight(track,fontHeight)))
-            {
-            char numBuf[SMALLBUF];
-            sprintLongWithCommas(numBuf, maxSafeHeight);
-            printf("warning: image is over %s pixels high at "
-                "track '%s',<BR>remaining tracks set to hide "
-                "for this view.<BR>\n", numBuf, track->tdb->shortLabel);
-            safeHeight = FALSE;
-            track->limitedVis = tvHide;
-            track->limitedVisSet = TRUE;
-            }
-        }
     }
 flatTracksSort(&flatTracks); // Now we should have a perfectly good flat track list!
 struct track *prevTrack = NULL;
 for (flatTrack = flatTracks,prevTrack=NULL; flatTrack != NULL; flatTrack = flatTrack->next)
     {
     track = flatTrack->track;
-    if (maxSafeHeight < (pixHeight+trackPlusLabelHeight(track,fontHeight)))
+    assert(track->limitedVis != tvHide);
+    int totalHeight = pixHeight+trackPlusLabelHeight(track,fontHeight);
+    if (maxSafeHeight < totalHeight)
         {
         char numBuf[SMALLBUF];
         sprintLongWithCommas(numBuf, maxSafeHeight);
         printf("warning: image is over %s pixels high at "
             "track '%s',<BR>remaining tracks set to hide "
             "for this view.<BR>\n", numBuf, track->tdb->shortLabel);
+        warn("warning: image is over %s pixels high (%d pix) at "
+            "track '%s' (%s),<BR>remaining tracks set to hide "
+            "for this view.", numBuf, totalHeight, track->tdb->shortLabel,track->track);
         safeHeight = FALSE;
         track->limitedVis = tvHide;
         track->limitedVisSet = TRUE;
         }
     if (track->limitedVis != tvHide)
         {
         track->prevTrack = prevTrack; // Important for keeping track of conditional center labels!
         pixHeight += trackPlusLabelHeight(track, fontHeight);
         prevTrack = track;
         }
     }
 
 imagePixelHeight = pixHeight;
 if (psOutput)
     {
@@ -2101,36 +2102,36 @@
 findTrackColors(hvg, trackList);
 
 // Good to go ahead and add all imgTracks regardless of buttons, left label, centerLabel, etc.
 if(theImgBox)
     {
     if (rulerMode != tvHide)
         {
         curImgTrack = imgBoxTrackFindOrAdd(theImgBox,NULL,RULER_TRACK_NAME,rulerMode,FALSE,IMG_FIXEDPOS); // No tdb, no centerlabel, not reorderable
         }
 
     for (flatTrack = flatTracks; flatTrack != NULL; flatTrack = flatTrack->next)
         {
         track = flatTrack->track;
         if (track->limitedVis != tvHide)
             {
-            #ifdef SUBTRACKS_HAVE_VIS
             if(track->labelColor == track->ixColor && track->ixColor == 0)
                 track->ixColor = hvGfxFindRgb(hvg, &track->color);
-            #endif//def SUBTRACKS_HAVE_VIS
             int order = flatTrack->order;
             curImgTrack = imgBoxTrackFindOrAdd(theImgBox,track->tdb,NULL,track->limitedVis,isCenterLabelIncluded(track),order);
+            if (trackShouldUseAjaxRetrieval(track))
+                imgTrackMarkForAjaxRetrieval(curImgTrack,TRUE);
             }
         }
     }
 
 /* Draw mini-buttons. */
 if (withLeftLabels && psOutput == NULL)
     {
     int butOff;
     boolean grayButtonGroup = FALSE;
     struct group *lastGroup = NULL;
     y = gfxBorder;
     if (rulerMode != tvHide)
         {
         /* draw button for Base Position pseudo-track */
         int height = basePositionHeight;
@@ -2269,30 +2270,33 @@
         }
     for (flatTrack = flatTracks; flatTrack != NULL; flatTrack = flatTrack->next)
         {
         track = flatTrack->track;
         if (track->limitedVis == tvHide)
             continue;
          if(theImgBox)
             {
             // side label slice for tracks
             sliceHeight      = trackPlusLabelHeight(track, fontHeight);
             sliceOffsetY     = y;
             curImgTrack = imgBoxTrackFind(theImgBox,track->tdb,NULL);
             curSlice    = imgTrackSliceUpdateOrAdd(curImgTrack,stSide,theSideImg,NULL,sliceWidth[stSide],sliceHeight,sliceOffsetX[stSide],sliceOffsetY);
             curMap      = sliceMapFindOrStart(curSlice,track->tdb->track,NULL); // No common linkRoot
             }
+        if (trackShouldUseAjaxRetrieval(track))
+            y += REMOTE_TRACK_HEIGHT;
+        else
             y = doLeftLabels(track, hvgSide, font, y);
         }
     }
 else
     {
     leftLabelX = leftLabelWidth = 0;
     }
 
 /* Draw guidelines. */
 if (withGuidelines)
     {
     struct hvGfx *bgImg = hvg; // Default to the one image
     boolean exists = FALSE;
     if(theImgBox)
         {
@@ -2360,30 +2364,33 @@
         track = flatTrack->track;
         if (track->limitedVis == tvHide)
             continue;
 
         if(theImgBox)
             {
             // center label slice of tracks Must always make, even if the centerLabel is empty
             sliceHeight      = fontHeight;
             sliceOffsetY     = y;
             curImgTrack = imgBoxTrackFind(theImgBox,track->tdb,NULL);
             curSlice    = imgTrackSliceUpdateOrAdd(curImgTrack,stCenter,theOneImg,NULL,sliceWidth[stData],sliceHeight,sliceOffsetX[stData],sliceOffsetY);
             curMap      = sliceMapFindOrStart(curSlice,track->tdb->track,NULL); // No common linkRoot
             if (isCenterLabelConditional(track))
                 imgTrackUpdateCenterLabelSeen(curImgTrack,isCenterLabelConditionallySeen(track)?clNowSeen:clNotSeen);
             }
+        if (trackShouldUseAjaxRetrieval(track))
+            y += REMOTE_TRACK_HEIGHT;
+        else
         y = doCenterLabels(track, track, hvg, font, y);
         }
     hvGfxUnclip(hvg);
     }
 
 /* Draw tracks. */
     {
     long lastTime = 0;
     y = yAfterRuler;
     if (measureTiming)
         lastTime = clock1000();
     for (flatTrack = flatTracks; flatTrack != NULL; flatTrack = flatTrack->next)
         {
         track = flatTrack->track;
         if (track->limitedVis == tvHide)
@@ -2392,30 +2399,33 @@
         int centerLabelHeight = (isCenterLabelIncluded(track) ? fontHeight : 0);
         int yStart = y + centerLabelHeight;
         int yEnd   = y + trackPlusLabelHeight(track, fontHeight);
         if(theImgBox)
             {
             // data slice of tracks
             sliceOffsetY     = yStart;
             sliceHeight      = yEnd - yStart - 1;
             curImgTrack = imgBoxTrackFind(theImgBox,track->tdb,NULL);
             if(sliceHeight > 0)
                 {
                 curSlice    = imgTrackSliceUpdateOrAdd(curImgTrack,stData,theOneImg,NULL,sliceWidth[stData],sliceHeight,sliceOffsetX[stData],sliceOffsetY);
                 curMap      = sliceMapFindOrStart(curSlice,track->tdb->track,NULL); // No common linkRoot
                 }
             }
+        if (trackShouldUseAjaxRetrieval(track))
+            y += REMOTE_TRACK_HEIGHT;
+        else
             y = doDrawItems(track, hvg, font, y, &lastTime);
 
         if (theImgBox && track->limitedVis == tvDense && tdbIsCompositeChild(track->tdb))
             mapBoxToggleVis(hvg, 0, yStart,tl.picWidth, sliceHeight,track); // Strange mabBoxToggleLogic handles reverse complement itself so x=0, width=tl.picWidth
 
         if(yEnd!=y)
             warn("Slice height does not add up.  Expecting %d != %d actual",yEnd - yStart - 1,y-yStart);
         }
     y++;
     }
 /* if a track can draw its left labels, now is the time since it
  *  knows what exactly happened during drawItems
  */
 if (withLeftLabels)
     {
@@ -2423,31 +2433,33 @@
     for (flatTrack = flatTracks; flatTrack != NULL; flatTrack = flatTrack->next)
         {
         track = flatTrack->track;
         if (track->limitedVis == tvHide)
                 continue;
         if(theImgBox)
             {
             // side label slice of tracks
             sliceHeight      = trackPlusLabelHeight(track, fontHeight);
             sliceOffsetY     = y;
             curImgTrack = imgBoxTrackFind(theImgBox,track->tdb,NULL);
             curSlice    = imgTrackSliceUpdateOrAdd(curImgTrack,stSide,theSideImg,NULL,sliceWidth[stSide],sliceHeight,sliceOffsetX[stSide],sliceOffsetY);
             curMap      = sliceMapFindOrStart(curSlice,track->tdb->track,NULL); // No common linkRoot
             }
 
-        if (track->drawLeftLabels != NULL)
+        if (trackShouldUseAjaxRetrieval(track))
+            y += REMOTE_TRACK_HEIGHT;
+        else if (track->drawLeftLabels != NULL)
             y = doOwnLeftLabels(track, hvgSide, font, y);
         else
             y += trackPlusLabelHeight(track, fontHeight);
         }
     }
 
 
 /* Make map background. */
 y = yAfterRuler;
 for (flatTrack = flatTracks; flatTrack != NULL; flatTrack = flatTrack->next)
     {
     track = flatTrack->track;
     if (track->limitedVis != tvHide)
         {
         if(theImgBox)
@@ -2952,30 +2964,35 @@
   sprintf(buf, "%s %s", ctFileName, itemName);
 else
   sprintf(buf, "%s NoItemName", ctFileName);
 return buf;
 }
 
 
 void coloredExonMethodsFromCt(struct track *tg)
 /* same as coloredExonMethods but different loader. */
 {
 linkedFeaturesSeriesMethods(tg);
 tg->loadItems = ctLoadColoredExon;
 tg->canPack = TRUE;
 }
 
+void dontLoadItems(struct track *tg)
+/* No-op loadItems when we aren't going to try. */
+{
+}
+
 struct track *newCustomTrack(struct customTrack *ct)
 /* Make up a new custom track. */
 {
 struct track *tg = NULL;
 struct trackDb *tdb = ct->tdb;
 boolean useItemRgb = FALSE;
 char *typeOrig = tdb->type;
 char *typeDupe = cloneString(typeOrig);
 char *typeParam = typeDupe;
 char *type = nextWord(&typeParam);
 
 if (ct->dbTrack)
     {
     // make sure we can connect
     struct sqlConnection *conn = hAllocConn(CUSTOM_TRASH);
@@ -3003,45 +3020,49 @@
 else if (sameString(type, "wig"))
     {
     tg = trackFromTrackDb(tdb);
     if (ct->dbTrack)
     tg->loadItems = wigLoadItems;
     else
     tg->loadItems = ctWigLoadItems;
     tg->customPt = ct;
     tg->nextItemButtonable = FALSE;
     }
 else if (sameString(type, "bigWig"))
     {
     tg = trackFromTrackDb(tdb);
     tg->bbiFile = ct->bbiFile;
     tg->nextItemButtonable = FALSE;
+    if (trackShouldUseAjaxRetrieval(tg))
+        tg->loadItems = dontLoadItems;
     }
 else if (sameString(type, "bigBed"))
     {
     struct bbiFile *bbi = ct->bbiFile;
 
     /* Find field counts, and from that revise the tdb->type to be more complete. */
     char extra = (bbi->fieldCount > bbi->definedFieldCount ? '+' : '.');
     char typeBuf[64];
     safef(typeBuf, sizeof(typeBuf), "bigBed %d %c", bbi->definedFieldCount, extra);
     tdb->type = cloneString(typeBuf);
 
     /* Finish wrapping track around tdb. */
     tg = trackFromTrackDb(tdb);
     tg->bbiFile = bbi;
     tg->nextItemButtonable = FALSE;
+    if (trackShouldUseAjaxRetrieval(tg))
+        tg->loadItems = dontLoadItems;
     }
 else if (sameString(type, "bedGraph"))
     {
     tg = trackFromTrackDb(tdb);
     tg->canPack = FALSE;
     tg->customPt = ct;
     ct->wigFile = ctFileName;
     tg->mapItemName = ctMapItemName;
     tg->nextItemButtonable = FALSE;
     }
 else if (sameString(type, "bed"))
     {
     tg = trackFromTrackDb(tdb);
     if (ct->fieldCount < 8)
 	{
@@ -3097,30 +3118,32 @@
     tg->nextItemButtonable = TRUE;
     tg->customPt = ct;
     }
 else if (sameString(type, "encodePeak"))
     {
     tg = trackFromTrackDb(tdb);
     encodePeakMethodsCt(tg);
     tg->nextItemButtonable = TRUE;
     tg->customPt = ct;
     }
 else if (sameString(type, "bam"))
     {
     tg = trackFromTrackDb(tdb);
     tg->customPt = ct;
     bamMethods(tg);
+    if (trackShouldUseAjaxRetrieval(tg))
+        tg->loadItems = dontLoadItems;
     tg->mapItemName = ctMapItemName;
     hashAdd(tdb->settingsHash, BASE_COLOR_USE_SEQUENCE, cloneString("lfExtra"));
     hashAdd(tdb->settingsHash, BASE_COLOR_DEFAULT, cloneString("diffBases"));
     hashAdd(tdb->settingsHash, SHOW_DIFF_BASES_ALL_SCALES, cloneString("."));
     hashAdd(tdb->settingsHash, INDEL_DOUBLE_INSERT, cloneString("on"));
     hashAdd(tdb->settingsHash, INDEL_QUERY_INSERT, cloneString("on"));
     hashAdd(tdb->settingsHash, INDEL_POLY_A, cloneString("on"));
     hashAdd(tdb->settingsHash, "showDiffBasesMaxZoom", cloneString("100"));
     }
 else if (sameString(type, "makeItems"))
     {
     tg = trackFromTrackDb(tdb);
     makeItemsMethods(tg);
     tg->nextItemButtonable = TRUE;
     tg->customPt = ct;
@@ -4153,35 +4176,30 @@
                  int xOff, int yOff, int width, MgFont *font, Color color,
                  enum trackVisibility vis)
 /* This is a stub drawItems handler to be swapped in for the usual drawItems when the window
  * size is larger than the threshold specified by trackDb setting maxWindowToDraw. */
 {
 int maxWinToDraw = getMaxWindowToDraw(tg->tdb);
 char commafied[256];
 sprintLongWithCommas(commafied, maxWinToDraw);
 char message[512];
 safef(message, sizeof(message), "zoom in to <= %s bases to view items", commafied);
 Color yellow = hvGfxFindRgb(hvg, &undefinedYellowColor);
 hvGfxBox(hvg, xOff, yOff, width, tg->heightPer, yellow);
 hvGfxTextCentered(hvg, xOff, yOff, width, tg->heightPer, MG_BLACK, font, message);
 }
 
-static void dontLoadItems(struct track *tg)
-/* No-op loadItems when we aren't going to try. */
-{
-}
-
 static void checkMaxWindowToDraw(struct track *tg)
 /* If (winEnd - winStart) > trackDb setting maxWindowToDraw, force track to a dense line
  * that will ask the user to zoom in closer to see track items and return TRUE so caller
  * can skip loading items. */
 {
 int maxWinToDraw = getMaxWindowToDraw(tg->tdb);
 if (tdbIsComposite(tg->tdb))
     {
     struct track *subtrack;
     for (subtrack = tg->subtracks;  subtrack != NULL;  subtrack = subtrack->next)
 	{
 	if (!isSubtrackVisible(subtrack))
 	    continue;
 	maxWinToDraw = getMaxWindowToDraw(subtrack->tdb);
 	if (maxWinToDraw > 1 && (winEnd - winStart) > maxWinToDraw)
@@ -4218,31 +4236,30 @@
 hPrintf( "}\n");
 hPrintf("</script>\n");
 }
 
 void jsCommandDispatch(char *command, struct track *trackList)
 /* Dispatch a command sent to us from some javaScript event.
  * This gets executed after the track list is built, but before
  * the track->loadItems methods are called.  */
 {
 if (startsWithWord("makeItems", command))
     makeItemsJsCommand(command, trackList, trackHash);
 else
     warn("Unrecognized jsCommand %s", command);
 }
 
-#ifdef SUBTRACKS_HAVE_VIS
 void parentChildCartCleanup(struct track *trackList,struct cart *newCart,struct hash *oldVars)
 /* When composite/view settings changes, remove subtrack specific vis
    When superTrackChild is found and selected, shape superTrack to match. */
 {
 struct track *track = trackList;
 for (;track != NULL; track = track->next)
     {
     boolean shapedByubtrackOverride = FALSE;
     boolean cleanedByContainerSettings = FALSE;
 
     if (tdbIsContainer(track->tdb))
         {
         shapedByubtrackOverride = cartTdbTreeMatchSubtrackVis(cart,track->tdb);
         if(shapedByubtrackOverride)
             track->visibility = tdbVisLimitedByAncestors(cart,track->tdb,TRUE,TRUE);
@@ -4255,31 +4272,30 @@
         { // Need to update track visibility
         // Unfortunately, since supertracks are not in trackList, this occurs on superChildren,
         // So now we need to find the supertrack and take changed cart values of its children
         struct slRef *childRef;
         for(childRef = track->tdb->parent->children;childRef != NULL;childRef = childRef->next)
             {
             struct trackDb * childTdb = childRef->val;
             struct track *child = hashFindVal(trackHash, childTdb->track);
             char *cartVis = cartOptionalString(cart,child->track);
             if (cartVis)
                 child->visibility = hTvFromString(cartVis);
             }
         }
     }
 }
-#endif///def SUBTRACKS_HAVE_VIS
 
 void doTrackForm(char *psOutput, struct tempName *ideoTn)
 /* Make the tracks display form with the zoom/scroll buttons and the active
  * image.  If the ideoTn parameter is not NULL, it is filled in if the
  * ideogram is created.  */
 {
 struct group *group;
 struct track *track;
 char *freezeName = NULL;
 boolean hideAll = cgiVarExists("hgt.hideAll");
 boolean defaultTracks = cgiVarExists("hgt.reset");
 boolean showedRuler = FALSE;
 boolean showTrackControls = cartUsualBoolean(cart, "trackControlsOnMain", TRUE);
 long thisTime = 0, lastTime = 0;
 char *clearButtonJavascript;
@@ -4318,33 +4334,31 @@
     uglyTime("Time before getTrackList");
 trackList = getTrackList(&groupList, defaultTracks ? -1 : -2);
 makeGlobalTrackHash(trackList);
 #ifdef SOON
 if (measureTiming)
     uglyTime("getTrackList");
 #endif /* SOON */
 
 // honor defaultImgOrder
 if(cgiVarExists("hgt.defaultImgOrder"))
     {
     char wildCard[32];
     safef(wildCard,sizeof(wildCard),"*_%s",IMG_ORDER_VAR);
     cartRemoveLike(cart, wildCard);
     }
-#ifdef SUBTRACKS_HAVE_VIS
 parentChildCartCleanup(trackList,cart,oldVars); // Subtrack settings must be removed when composite/view settings are updated
-#endif///def SUBTRACKS_HAVE_VIS
 
 
 /* Honor hideAll and visAll variables */
 if (hideAll || defaultTracks)
     {
     int vis = (hideAll ? tvHide : -1);
     changeTrackVis(groupList, NULL, vis);
     }
 
 /* Before loading items, deal with the next/prev item arrow buttons if pressed. */
 if (cgiVarExists("hgt.nextItem"))
     doNextPrevItem(TRUE, cgiUsualString("hgt.nextItem", NULL));
 else if (cgiVarExists("hgt.prevItem"))
     doNextPrevItem(FALSE, cgiUsualString("hgt.prevItem", NULL));