f5ba7e5371b8bcf6c260d065b971e57c09eca1ad
Merge parents 189bd07 d24ed48
kate
  Wed Sep 25 10:56:06 2019 -0700
Merging

diff --cc src/hg/hgTracks/hgTracks.c
index 6d319cf,f5125d5..e883494
--- src/hg/hgTracks/hgTracks.c
+++ src/hg/hgTracks/hgTracks.c
@@@ -4579,137 -4556,39 +4557,142 @@@
  struct window *window;
  for (window=windows, winTrack=track; window; window=window->next, winTrack=winTrack->nextWindow)
      {
      setGlobalsFromWindow(window);
  
      int trackHeight =  trackPlusLabelHeight(winTrack, fontHeight);
  
      if (trackHeight > maxHeight)
  	maxHeight = trackHeight;
      }
  setGlobalsFromWindow(windows); // first window
  
  flatTrack->maxHeight = maxHeight;
  }
  
- char *collapseEmptySubtracksSetting(struct track *track)
 -boolean doCollapseEmptySubtracks(struct track *track)
 -/* Suppress display of empty subtracks. Initial support only for bed's. */
++char *hideEmptySubtracksSetting(struct track *track)
 +/* Setting to suppress display of empty subtracks */
  {
 +if (!tdbIsComposite(track->tdb))
 +    return FALSE;
- return trackDbSetting(track->tdb, "collapseEmptySubtracks");
+ char *collapse = trackDbSetting(track->tdb, "hideEmptySubtracks");
+ if (!collapse)
+     // previous syntax (not documented, but used by Regeneron)
+     collapse = trackDbSetting(track->tdb, "collapseEmptySubtracks");
 -return (collapse && (sameWord(collapse, "on") ||
 -                                        sameWord(collapse, "true")));
++return (collapse);
 +}
 +
- boolean doCollapseEmptySubtracksNoMultiBed(struct track *track)
- /* TRUE if collapseEmptySubtracks setting is 'on' (no file specs for multiBed */
++boolean doHideEmptySubtracksNoMultiBed(struct track *track)
++/* TRUE if hideEmptySubtracks setting is 'on'  or 'true' (no file specs for multiBed */
 +{
- char *setting = collapseEmptySubtracksSetting(track);
- if (setting && sameString(setting, "on"))
++char *setting = hideEmptySubtracksSetting(track);
++if (setting && (sameString(setting, "on") || sameString(setting, "true")))
 +    return TRUE;
 +return FALSE;
 +}
 +
- boolean doCollapseEmptySubtracks(struct track *track, char **multiBedFile, char **subtrackIdFile)
++boolean doHideEmptySubtracks(struct track *track, char **multiBedFile, char **subtrackIdFile)
 +{
 +/* Support setting to suppress display of empty subtracks. 
 + * (Initial support only for bed's).
 + * 
-  * Format:  collapseEmptySubtracks on
++ * Format:  hideEmptySubtracks on
 + *              or
-  *          collapseEmptySubtracks multiBed.bed subtrackIds.tab
++ *          hideEmptySubtracks multiBed.bed subtrackIds.tab
 + * where multiBed.bed is a bed3Sources bigBed, generated with bedtools multiinter
 + *              post-processed by UCSC multiBed.pl tool
 + *      subtrackIds.tab is a tab-sep file: id subtrackName
 + */
- char *collapse = collapseEmptySubtracksSetting(track);
++char *collapse = hideEmptySubtracksSetting(track);
 +if (!collapse)
 +    return FALSE;
- if (doCollapseEmptySubtracksNoMultiBed(track))
++if (doHideEmptySubtracksNoMultiBed(track))
 +    return TRUE;
 +char *orig = cloneString(collapse);
 +char *words[2];
 +int wordCount = chopByWhite(collapse, words, ArraySize(words));
 +if (wordCount == 2)
 +    {
 +    if (multiBedFile)
 +        *multiBedFile = cloneString(hReplaceGbdb(words[0]));
 +    if (subtrackIdFile)
 +        *subtrackIdFile = cloneString(words[1]);
 +    return TRUE;
 +    }
- warn("Track %s collapseEmptySubtracks setting invalid: %s",
++warn("Track %s hideEmptySubtracks setting invalid: %s",
 +                track->track, orig);
 +return FALSE;
 +}
 +
 +struct hash *getNonEmptySubtracks(struct track *track)
 +{
 +/* Support setting to suppress display of empty subtracks. 
 + * (Initial support only for bed's).
 + * 
-  * Format:  collapseEmptySubtracks on
++ * Format:  hideEmptySubtracks on
 + *              or
-  *          collapseEmptySubtracks multiBed.bed subtrackIds.tab
++ *          hideEmptySubtracks multiBed.bed subtrackIds.tab
 + * where multiBed.bed is a bed3Sources bigBed, generated with bedtools multiinter
 + *              post-processed by UCSC multiBed.pl tool
 + *      subtrackIds.tab is a tab-sep file: id subtrackName
 + *
 + * Return hash with subtrack names as keys
 + */
 +
 +char *multiBedFile = NULL;
 +char *subtracksIdFile = NULL;
- if (!doCollapseEmptySubtracks(track, &multiBedFile, &subtracksIdFile))
++if (!doHideEmptySubtracks(track, &multiBedFile, &subtracksIdFile))
 +    return NULL;
 +if (!multiBedFile)
 +    return NULL;
 +
 +// load multiBed items in window
 +// TODO: filters here ?
 +// TODO:  protect against temporary network error ? */
 +struct lm *lm = lmInit(0);
 +struct bbiFile *bbi = bigBedFileOpen(multiBedFile);
 +struct bigBedInterval *bb, *bbList =  bigBedIntervalQuery(bbi, chromName, winStart, winEnd, 0, lm);
 +char *row[bbi->fieldCount];
 +char startBuf[16], endBuf[16];
 +struct hash *nonEmptySubtracksHash = hashNew(0);
 +for (bb = bbList; bb != NULL; bb = bb->next)
 +    {
 +    bigBedIntervalToRow(bb, chromName, startBuf, endBuf, row, ArraySize(row));
 +    // TODO: do this in bed3Sources.c
 +    char *idList = row[4];
 +    struct slName *ids = slNameListFromComma(idList);
 +    struct slName *id = NULL;
 +    for (id = ids; id != NULL; id = id->next)
 +        hashStore(nonEmptySubtracksHash, id->name);
 +    // TODO: free some stuff ?
 +    }
 +
 +// read file containing ids of subtracks 
 +struct lineFile *lf = udcWrapShortLineFile(subtracksIdFile, NULL, 0); 
 +char *words[2];
 +while (lineFileChopNext(lf, words, sizeof words))
 +    {
 +    char *id = words[0];
 +    char *name = words[1];
 +    if (hashLookup(nonEmptySubtracksHash, id))
 +        {
 +        hashStore(nonEmptySubtracksHash, cloneString(name));
 +        }
 +    }
 +lineFileClose(&lf);
 +return nonEmptySubtracksHash;
++
  }
  
  void makeActiveImage(struct track *trackList, char *psOutput)
  /* Make image and image map. */
  {
  struct track *track;
  MgFont *font = tl.font;
  struct hvGfx *hvg;
  struct tempName pngTn;
  char *mapName = "map";
  int fontHeight = mgFontLineHeight(font);
  int trackPastTabX = (withLeftLabels ? trackTabWidth : 0);
  int trackTabX = gfxBorder;
  int trackPastTabWidth = tl.picWidth - trackPastTabX;
  int pixWidth, pixHeight;
@@@ -4914,41 -4793,38 +4897,41 @@@
          safef(buffer, sizeof buffer,  "%s_imgOrd", name->name);
          cartRemove(cart, buffer);
          }
      }
  
  // Construct flatTracks
  for (track = trackList; track != NULL; track = track->next)
      {
      if (tdbIsComposite(track->tdb))
          {
          struct track *subtrack;
          if (isCompositeInAggregate(track))
              flatTracksAdd(&flatTracks,track,cart, orderedWiggles);
          else
              {
-             boolean doCollapse = doCollapseEmptySubtracksNoMultiBed(track);
 -            boolean doCollapse = doCollapseEmptySubtracks(track);
++            boolean doHideEmpties = doHideEmptySubtracksNoMultiBed(track);
 +                // If multibed was found, it has been used to suppress loading,
 +                // and subtracks lacking items in window are already set hidden
              for (subtrack = track->subtracks; subtrack != NULL; subtrack = subtrack->next)
                  {
                  if (!isSubtrackVisible(subtrack))
                      continue;
  
                  if (!isLimitedVisHiddenForAllWindows(subtrack) && 
--                        !(doCollapse && slCount(subtrack->items) == 0))
++                        !(doHideEmpties && slCount(subtrack->items) == 0))
 +                        // Ignore subtracks with no items in window
                      {
                      flatTracksAdd(&flatTracks,subtrack,cart, orderedWiggles);
                      }
                  }
              }
          }
      else
  	{	
  	if (!isLimitedVisHiddenForAllWindows(track))
  	    {
  	    flatTracksAdd(&flatTracks,track,cart, orderedWiggles);
  	    }
  	}
      }
  flatTracksSort(&flatTracks); // Now we should have a perfectly good flat track list!
@@@ -7252,52 -7109,30 +7216,52 @@@
  	    subtrack->drawItems = drawMaxWindowWarning;
  	    subtrack->limitedVis = tvDense;
  	    subtrack->limitedVisSet = TRUE;
  	    }
  	}
      }
  else if (maxWinToDraw > 1 && (winEnd - winStart) > maxWinToDraw)
      {
      tg->loadItems = dontLoadItems;
      tg->drawItems = drawMaxWindowWarning;
      tg->limitedVis = tvDense;
      tg->limitedVisSet = TRUE;
      }
  }
  
- static void checkCollapseEmptySubtracks(struct track *tg)
++static void checkHideEmptySubtracks(struct track *tg)
 +/* Suppress queries on subtracks w/o data in window (identified from multiIntersect file) */
 +{
 +if (!tdbIsComposite(tg->tdb))
 +    return;
 +struct hash *nonEmptySubtracksHash = getNonEmptySubtracks(tg);
 +if (!nonEmptySubtracksHash)
 +    return;
 +struct track *subtrack;
 +for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next)
 +    {
 +    if (!isSubtrackVisible(subtrack))
 +        continue;
 +    if (!hashLookup(nonEmptySubtracksHash, subtrack->track))
 +        {
 +        subtrack->loadItems = dontLoadItems;
 +        subtrack->limitedVis = tvHide;
 +        subtrack->limitedVisSet = TRUE;
 +        }
 +    }
 +}
 +
  void printTrackInitJavascript(struct track *trackList)
  {
  hPrintf("<input type='hidden' id='%s' name='%s' value=''>\n", hgtJsCommand, hgtJsCommand);
  }
  
  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);
  }
@@@ -7438,31 -7273,30 +7402,31 @@@
      pthread_mutex_unlock( &pfdMutex );
      if (allDone)
  	return NULL;
  
      long thisTime = 0, lastTime = 0;
  
      if (measureTiming)
  	lastTime = clock1000();
  
      /* protect against errAbort */
      struct errCatch *errCatch = errCatchNew();
      if (errCatchStart(errCatch))
  	{
  	pfd->done = FALSE;
  	checkMaxWindowToDraw(pfd->track);
- 	checkCollapseEmptySubtracks(pfd->track);
++	checkHideEmptySubtracks(pfd->track);
  	pfd->track->loadItems(pfd->track);
  	pfd->done = TRUE;
  	}
      errCatchEnd(errCatch);
      if (errCatch->gotError)
  	{
  	pfd->track->networkErrMsg = cloneString(errCatch->message->string);
  	pfd->done = TRUE;
  	}
      errCatchFree(&errCatch);
  
      if (measureTiming)
  	{
  	thisTime = clock1000();
  	pfd->track->loadTime = thisTime - lastTime;
@@@ -8084,32 -7918,30 +8048,32 @@@
  	}
  
      // TODO GALT
      /* load regular tracks */
      for (track = trackList; track != NULL; track = track->next)
  	{
  	if (track->visibility != tvHide)
  	    {
  	    if (!track->parallelLoading)
  		{
  		if (measureTiming)
  		    lastTime = clock1000();
  
  		checkMaxWindowToDraw(track);
  
- 		checkCollapseEmptySubtracks(track);     // TODO: Test with multi-window feature
++		checkHideEmptySubtracks(track);     // TODO: Test with multi-window feature
 +
  		checkIfWiggling(cart, track);
  
  		if (!loadHack)
  		    {
  		    track->loadItems(track);
  		    }
  		else
  		    {
  		    // TEMP HACK GALT REMOVE
  		    if (currentWindow == windows) // first window
  			{
  			track->loadItems(track);
  			}
  		    else
  			{