0e594d3b2ff344384b4cd9c24761fe2f5ec79a1e
Merge parents 3df0f0e 37a5223
tdreszer
  Thu Nov 10 09:40:02 2011 -0800
merge-o-matic mania
diff --cc src/hg/lib/hui.c
index 31b7bff,1f4d6d0..cb8975b
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@@ -16,34 -16,37 +16,38 @@@
  #include "chainDb.h"
  #include "netCart.h"
  #include "obscure.h"
  #include "wiggle.h"
  #include "phyloTree.h"
  #include "hgMaf.h"
  #include "udc.h"
  #include "customTrack.h"
  #include "encode/encodePeak.h"
  #include "mdb.h"
  #include "web.h"
  #include "hPrint.h"
  #include "fileUi.h"
  #include "bigBed.h"
  #include "bigWig.h"
 +#include "regexHelper.h"
  #include "vcfUi.h"
- 
- static char const rcsid[] = "$Id: hui.c,v 1.297 2010/06/02 19:27:51 tdreszer Exp $";
+ #include "vcf.h"
+ #include "errCatch.h"
+ #include "samAlignment.h"
+ #include "makeItemsItem.h"
+ #include "bedDetail.h"
+ #include "pgSnp.h"
  
  #define SMALLBUF 128
  #define MAX_SUBGROUP 9
  #define ADD_BUTTON_LABEL        "add"
  #define CLEAR_BUTTON_LABEL      "clear"
  #define JBUFSIZE 2048
  
  //#define PM_BUTTON "<A NAME=\"%s\"></A><A HREF=\"#%s\"><IMG height=18 width=18 onclick=\"return (setCheckBoxesThatContain('%s',%s,true,'%s','','%s') == false);\" id=\"btn_%s\" src=\"../images/%s\" alt=\"%s\"></A>\n"
  //#define DEF_BUTTON "<A NAME=\"%s\"></A><A HREF=\"#%s\"><IMG onclick=\"setCheckBoxesThatContain('%s',true,false,'%s','','%s'); return (setCheckBoxesThatContain('%s',false,false,'%s','_defOff','%s') == false);\" id=\"btn_%s\" src=\"../images/%s\" alt=\"%s\"></A>\n"
  //#define DEFAULT_BUTTON(nameOrId,anc,beg,contains) printf(DEF_BUTTON,(anc),(anc),(nameOrId),        (beg),(contains),(nameOrId),(beg),(contains),(anc),"defaults_sm.png","default")
  //#define    PLUS_BUTTON(nameOrId,anc,beg,contains) printf(PM_BUTTON, (anc),(anc),(nameOrId),"true", (beg),(contains),(anc),"add_sm.gif",   "+")
  //#define   MINUS_BUTTON(nameOrId,anc,beg,contains) printf(PM_BUTTON, (anc),(anc),(nameOrId),"false",(beg),(contains),(anc),"remove_sm.gif","-")
  #define PM_BUTTON  "<IMG height=18 width=18 onclick=\"setCheckBoxesThatContain('%s',%s,true,'%s','','%s');\" id=\"btn_%s\" src=\"../images/%s\" alt=\"%s\">\n"
  #define DEF_BUTTON "<IMG onclick=\"setCheckBoxesThatContain('%s',true,false,'%s','','%s'); setCheckBoxesThatContain('%s',false,false,'%s','_defOff','%s');\" id=\"btn_%s\" src=\"../images/%s\" alt=\"%s\">\n"
  #define DEFAULT_BUTTON(nameOrId,anc,beg,contains) printf(DEF_BUTTON,(nameOrId),        (beg),(contains),(nameOrId),(beg),(contains),(anc),"defaults_sm.png","default")
@@@ -3459,65 -3450,67 +3463,65 @@@
          if(notFirst)
              dyStringPrintf(dyClause, " AND ");
          dyStringAppend(dyClause, clause);
          freeMem(clause);
          notFirst = TRUE;
          }
      }
  if(dyStringLen(dyClause) == 0)
      {
      dyStringFree(&dyClause);
      return NULL;
      }
  return dyStringCannibalize(&dyClause);
  }
  
 -void filterBySetCfgUi(struct trackDb *tdb, filterBy_t *filterBySet, boolean onOneLine)
 +void filterBySetCfgUi(struct cart *cart, struct trackDb *tdb,
 +                      filterBy_t *filterBySet, boolean onOneLine)
  /* Does the UI for a list of filterBy structure */
  {
  if(filterBySet == NULL)
      return;
  
  #define FILTERBY_HELP_LINK  "<A HREF=\"../goldenPath/help/multiView.html\" TARGET=ucscHelp>help</A>"
  int count = slCount(filterBySet);
  if(count == 1)
      puts("<TABLE cellpadding=3><TR valign='top'>");
  else
      printf("<B>Filter items by:</B> (select multiple categories and items - %s)<TABLE cellpadding=3><TR valign='top'>\n",FILTERBY_HELP_LINK);
  
  filterBy_t *filterBy = NULL;
 -webIncludeResourceFile("ui.dropdownchecklist.css");
 -jsIncludeFile("ui.dropdownchecklist.js",NULL);
 -#ifdef NEW_JQUERY
 -jsIncludeFile("ddcl.js",NULL);
 -#endif///def NEW_JQUERY
 +if(cartOptionalString(cart, "ajax") == NULL)
 +    {
 +    webIncludeResourceFile("ui.dropdownchecklist.css");
 +    jsIncludeFile("ui.dropdownchecklist.js",NULL);
 +    jsIncludeFile("ddcl.js",NULL);
 +    }
  
  int ix=0;
  for(filterBy = filterBySet;filterBy != NULL; filterBy = filterBy->next)
      {
      puts("<TD>");
      if(count == 1)
          printf("<B>Filter by %s</B> (select multiple items - %s)",filterBy->title,FILTERBY_HELP_LINK);
      else
          printf("<B>%s</B>",filterBy->title);
      printf("<BR>\n");
  
      // TODO: columnCount (Number of filterBoxes per row) should be configurable through tdb setting
-     #define FILTER_BY_FORMAT "<SELECT id='fbc%d' name='%s.filterBy.%s' multiple style='display: none; font-size:.9em;' class='filterBy'><BR>\n"
-     printf(FILTER_BY_FORMAT,ix,tdb->track,filterBy->column);
 -    #ifdef NEW_JQUERY
 -        #define FILTER_BY_FORMAT "<SELECT id='fbc%d' name='%s' multiple style='display: none; font-size:.9em;' class='filterBy'><BR>\n"
 -    #else///ifndef NEW_JQUERY
 -        #define FILTER_BY_FORMAT "<SELECT id='fbc%d' name='%s' multiple style='display: none;' class='filterBy'><BR>\n"
 -    #endif///ndef NEW_JQUERY
++    #define FILTER_BY_FORMAT "<SELECT id='fbc%d' name='%s' multiple style='display: none; font-size:.9em;' class='filterBy'><BR>\n"
+     printf(FILTER_BY_FORMAT,ix,filterBy->htmlName);
      ix++;
      printf("<OPTION%s>All</OPTION>\n",(filterBy->slChoices == NULL || slNameInList(filterBy->slChoices,"All")?" SELECTED":""));
      struct slName *slValue;
  
      int ix=1;
      for(slValue=filterBy->slValues;slValue!=NULL;slValue=slValue->next,ix++)
          {
          char varName[32];
          char *label = NULL;
          char *name = NULL;
          if (filterBy->useIndex)
              {
              safef(varName, sizeof(varName), "%d",ix);
              name = varName;
              label = slValue->name;
@@@ -3696,82 -3686,65 +3700,86 @@@
      safef(htmlIdentifier, sizeof(htmlIdentifier), "%s.priority", tdb->track);
      char *cartHas = cartOptionalString(cart,htmlIdentifier);
      if(cartHas != NULL)
  	{
  	tdb->priority = atof(cartHas);
  	cartPriorities = TRUE;
  	}
      }
  slSort(tdbRefList, trackDbRefCmp);
  return cartPriorities;
  }
  
  void cfgByCfgType(eCfgType cType,char *db, struct cart *cart, struct trackDb *tdb,char *prefix, char *title, boolean boxed)
  // Methods for putting up type specific cfgs used by composites/subtracks in hui.c and exported for common use
  {
 -// NOTE: This is fixed on tdreszer_subCfg branch already!
 -if (tdbIsComposite(tdb) && tdbIsSubtrack(tdb->subtracks))
 -    tdb = tdb->subtracks;// composite without view should pass in subtrack as example track!
 +#ifdef SUBTRACK_CFG
 +// When only one subtrack, then show it's cfg settings instead of composite/view level settings
 +// This simplifies the UI where hgTrackUi won't have 2 levels of cfg,
 +// while hgTracks still supports rightClick cfg of the subtrack.
 +if (configurableByAjax(tdb,cType) > 0) // Only if subtrack's configurable by ajax do we consider this option
 +    {
 +    if (tdbIsComposite(tdb)                       // called for the composite
 +    && !tdbIsCompositeView(tdb->subtracks)        // and there is no view level
 +    && slCount(tdb->subtracks) == 1)              // and there is only one subtrack
 +        {
 +        //warn("What do you mean by having a composite (%s) with only one subtrack (%s) ???",tdb->track,tdb->subtracks->track);
 +        tdb = tdb->subtracks; // show subtrack cfg instead
 +        prefix = tdb->track;
 +        }
-     else if (tdb->parent != NULL                 // called with subtrack (tdb is never a view)
-         && tdbIsCompositeView(tdb->parent)       // subtrack has view
-         && differentString(prefix,tdb->track)    // and this has been called FOR the view
-         && slCount(tdb->parent->subtracks) == 1) // and view has only one subtrack
++    else if (tdbIsSubtrack(tdb)                   // called with subtrack
++         && tdbIsCompositeView(tdb->parent)       // subtrack has view
++         && differentString(prefix,tdb->track)    // and this has been called FOR the view
++         && slCount(tdb->parent->subtracks) == 1) // and view has only one subtrack
 +        prefix = tdb->track; // removes reference to view level
 +    }
 +#endif///def SUBTRACK_CFG
++// composite without view should pass in subtrack as example track!
++if (tdbIsComposite(tdb) && !tdbIsCompositeView(tdb->subtracks))
++    tdb = tdb->subtracks;
+ 
  switch(cType)
      {
      case cfgBedScore:
--	{
--	char *scoreMax = trackDbSettingClosestToHome(tdb, SCORE_FILTER _MAX);
--	int maxScore = (scoreMax ? sqlUnsigned(scoreMax):1000);
--	scoreCfgUi(db, cart,tdb,prefix,title,maxScore,boxed);
--	}
--	break;
++                        {
++                        char *scoreMax = trackDbSettingClosestToHome(tdb, SCORE_FILTER _MAX);
++                        int maxScore = (scoreMax ? sqlUnsigned(scoreMax):1000);
++                        scoreCfgUi(db, cart,tdb,prefix,title,maxScore,boxed);
++                        }
++                        break;
      case cfgPeak:
                          encodePeakCfgUi(cart,tdb,prefix,title,boxed);
                          break;
      case cfgWig:        wigCfgUi(cart,tdb,prefix,title,boxed);
                          break;
      case cfgWigMaf:     wigMafCfgUi(cart,tdb,prefix,title,boxed, db);
                          break;
      case cfgGenePred:   genePredCfgUi(cart,tdb,prefix,title,boxed);
                          break;
      case cfgChain:      chainCfgUi(db,cart,tdb,prefix,title,boxed, NULL);
                          break;
--    case cfgNetAlign:	netAlignCfgUi(db,cart,tdb,prefix,title,boxed);
++    case cfgNetAlign:   netAlignCfgUi(db,cart,tdb,prefix,title,boxed);
 +                        break;
 +    case cfgBedFilt:    bedFiltCfgUi(cart,tdb,prefix,title, boxed);
-                  	break;
+                         break;
 -    case cfgBedFilt:    bedUi(tdb,cart,title, boxed);
 -                 	break;
  #ifdef USE_BAM
      case cfgBam:        bamCfgUi(cart, tdb, prefix, title, boxed);
--			break;
++                        break;
  #endif
--    case cfgVcf:	vcfCfgUi(cart, tdb, prefix, title, boxed);
--			break;
--    case cfgPsl:	pslCfgUi(db,cart,tdb,prefix,title,boxed);
++    case cfgVcf:        vcfCfgUi(cart, tdb, prefix, title, boxed);
++                        break;
++    case cfgPsl:        pslCfgUi(db,cart,tdb,prefix,title,boxed);
                          break;
      default:            warn("Track type is not known to multi-view composites. type is: %d ", cType);
                          break;
      }
  }
  
  char *encodeRestrictionDate(char *db,struct trackDb *trackDb,boolean excludePast)
  /* Create a string for ENCODE restriction date of this track
     if return is not null, then free it after use */
  {
  if (!trackDb)
      return NULL;
  
  char *date = NULL;
  
@@@ -4867,171 -4742,163 +4875,195 @@@
              printf("<TD align='left'%s> (%d to %d)",altLabel,minLimit, maxLimit);
          else if(minLimit != NO_VALUE)
              printf("<TD align='left'%s> (minimum %d)",altLabel,minLimit);
          else if(maxLimit != NO_VALUE)
              printf("<TD align='left'%s> (maximum %d)",altLabel,maxLimit);
          else
              printf("<TD align='left'%s",altLabel);
          }
      puts("</TR>");
      return TRUE;
      }
  return FALSE;
  }
  
  
- static int numericFiltersShowAll(struct cart *cart, struct trackDb *tdb, boolean *opened, boolean boxed,
 -#ifdef ALL_SCORE_FILTERS_LOGIC
+ static int numericFiltersShowAll(char *db, struct cart *cart, struct trackDb *tdb, boolean *opened, boolean boxed,
 -                               boolean compositeLevel,char *name, char *title)
 +                               boolean viewLevel,char *name, char *title)
  // Shows all *Filter style filters.  Note that these are in random order and have no graceful title
  {
  int count = 0;
  struct slName *filterSettings = trackDbSettingsWildMatch(tdb, "*Filter");
  if (filterSettings)
      {
      puts("<BR>");
      struct slName *filter = NULL;
-     struct extraField *extras = extraFieldsGet(tdb);
+ #ifdef EXTRA_FIELDS_SUPPORT
+     struct extraField *extras = extraFieldsGet(db,tdb);
+ #else///ifndef EXTRA_FIELDS_SUPPORT
+     struct sqlConnection *conn = hAllocConnTrack(db, tdb);
+     struct asObject *as = asForTdb(conn, tdb);
+     hFreeConn(&conn);
+ #endif///ndef EXTRA_FIELDS_SUPPORT
  
      while ((filter = slPopHead(&filterSettings)) != NULL)
          {
 -        if (differentString(filter->name,"noScoreFilter") && differentString(filter->name,"scoreFilter")) // TODO: scoreFilter could be included
 +        if (differentString(filter->name,NO_SCORE_FILTER) && differentString(filter->name,SCORE_FILTER)) // TODO: scoreFilter could be included
              {
              // Determine floating point or integer
              char *setting = trackDbSetting(tdb, filter->name);
              boolean isFloat = (strchr(setting,'.') != NULL);
  
              char *scoreName = cloneString(filter->name);
              char *field = filter->name;   // No need to clone: will be thrown away at end of cycle
              int ix = strlen(field) - strlen("Filter");
              assert(ix > 0);
              field[ix] = '\0';
  
+         #ifdef EXTRA_FIELDS_SUPPORT
              if (extras != NULL)
                  {
                  struct extraField *extra = extraFieldsFind(extras, field);
                  if (extra != NULL)
                      { // Found label so replace field
                      field = extra->label;
                      if (!isFloat)
                          isFloat = (extra->type == ftFloat);
                      }
                  }
+         #else///ifndef EXTRA_FIELDS_SUPPORT
+             if (as != NULL)
+                 {
+                 struct asColumn *asCol = asColumnFind(as, field);
+                 if (asCol != NULL)
+                     { // Found label so replace field
+                     field = asCol->comment;
+                     if (!isFloat)
+                         isFloat = asTypesIsFloating(asCol->lowType->type);
+                     }
+                 }
+         #endif///ndef EXTRA_FIELDS_SUPPORT
              char label[128];
              safef(label,sizeof(label),"Minimum %s",field);
 -            showScoreFilter(cart,tdb,opened,boxed,compositeLevel,name,title,label,scoreName,isFloat);
 +            showScoreFilter(cart,tdb,opened,boxed,viewLevel,name,title,label,scoreName,isFloat);
              freeMem(scoreName);
              count++;
              }
          slNameFree(&filter);
          }
+ #ifdef EXTRA_FIELDS_SUPPORT
      if (extras != NULL)
          extraFieldsFree(&extras);
+ #else///ifndef EXTRA_FIELDS_SUPPORT
+     if (as != NULL)
+         asObjectFree(&as);
+ #endif///ndef EXTRA_FIELDS_SUPPORT
      }
  if (count > 0)
      puts("</TABLE>");
  return count;
  }
 -#endif///def ALL_SCORE_FILTERS_LOGIC
 +
 +
 +boolean bedScoreHasCfgUi(struct trackDb *tdb)
 +// Confirms that this track has a bedScore Cfg UI
 +{
 +// Assumes that cfgType == cfgBedScore
 +if (trackDbSettingClosestToHome(tdb, FILTER_BY))
 +    return TRUE;
 +if (trackDbSettingClosestToHome(tdb, GRAY_LEVEL_SCORE_MIN))
 +    return TRUE;
 +boolean blocked = FALSE;
 +struct slName *filterSettings = trackDbSettingsWildMatch(tdb, "*Filter");
 +if (filterSettings != NULL)
 +    {
 +    boolean one = FALSE;
 +    struct slName *oneFilter = filterSettings;
 +    for (;oneFilter != NULL;oneFilter=oneFilter->next)
 +        {
 +        if (sameWord(NO_SCORE_FILTER,oneFilter->name))
 +            {
 +            blocked = TRUE;
 +            continue;
 +            }
 +        if (differentString(oneFilter->name,SCORE_FILTER)) // scoreFilter is implicit but could be blocked
 +            {
 +            one = TRUE;
 +            break;
 +            }
 +        }
 +    slNameFreeList(&filterSettings);
 +    if (one)
 +        return TRUE;
 +    }
 +if (!blocked)  // scoreFilter is implicit unless NO_SCORE_FILTER
 +    return TRUE;
 +
 +return FALSE;
 +}
  
  
  void scoreCfgUi(char *db, struct cart *cart, struct trackDb *tdb, char *name, char *title,  int maxScore, boolean boxed)
  /* Put up UI for filtering bed track based on a score */
  {
  char option[256];
 -boolean compositeLevel = isNameAtCompositeLevel(tdb,name);
 +boolean viewLevel = isNameAtCompositeLevel(tdb,name);
  boolean skipScoreFilter = FALSE;
  boolean bigBed = startsWith("bigBed",tdb->type);
  
  if (!bigBed)  // bigBed filters are limited!
      {
 -    #ifdef ALL_SCORE_FILTERS_LOGIC
      // Numeric filters are first
      boolean isBoxOpened = FALSE;
-     if (numericFiltersShowAll(cart, tdb, &isBoxOpened, boxed, viewLevel, name, title) > 0)
 -    if (numericFiltersShowAll(db, cart, tdb, &isBoxOpened, boxed, compositeLevel, name, title) > 0)
++    if (numericFiltersShowAll(db, cart, tdb, &isBoxOpened, boxed, viewLevel, name, title) > 0)
          skipScoreFilter = TRUE;
 -    #endif///def ALL_SCORE_FILTERS_LOGIC
  
      // Add any multi-selects next
      filterBy_t *filterBySet = filterBySetGet(tdb,cart,name);
      if(filterBySet != NULL)
          {
          if(!tdbIsComposite(tdb) && cartOptionalString(cart, "ajax") == NULL)
              jsIncludeFile("hui.js",NULL);
  
          if (!isBoxOpened)   // Note filterBy boxes are not double "boxed", if there are no other filters
              printf("<BR>");
 -        filterBySetCfgUi(tdb,filterBySet,TRUE);
 +        filterBySetCfgUi(cart,tdb,filterBySet,TRUE);
          filterBySetFree(&filterBySet);
          skipScoreFilter = TRUE;
          }
  
      // For no good reason scoreFilter is incompatible with filterBy and or numericFilters
      // FIXME scoreFilter should be implemented inside numericFilters and is currently specificly excluded to avoid unexpected changes
      if (skipScoreFilter)
          {
 -        #ifdef ALL_SCORE_FILTERS_LOGIC
          if (isBoxOpened)
              cfgEndBox(boxed);
 -        #endif///def ALL_SCORE_FILTERS_LOGIC
  
          return; // Cannot have both '*filter' and 'scoreFilter'
          }
      }
  
  boolean scoreFilterOk = (trackDbSettingClosestToHome(tdb, NO_SCORE_FILTER) == NULL);
  boolean glvlScoreMin = (trackDbSettingClosestToHome(tdb, GRAY_LEVEL_SCORE_MIN) != NULL);
  if (! (scoreFilterOk || glvlScoreMin))
      return;
  boxed = cfgBeginBoxAndTitle(tdb, boxed, title);
  
  if (scoreFilterOk)
      {
      int minLimit=0,maxLimit=maxScore,minVal=0,maxVal=maxScore;
 -    getScoreIntRangeFromCart(cart,tdb,SCORE_FILTER,&minLimit,&maxLimit,&minVal,&maxVal);
 +    getScoreIntRangeFromCart(cart,tdb,viewLevel,SCORE_FILTER,&minLimit,&maxLimit,&minVal,&maxVal);
  
      boolean filterByRange = trackDbSettingClosestToHomeOn(tdb, SCORE_FILTER _BY_RANGE);
      if (!bigBed && filterByRange)
          {
          puts("<B>Filter score range:  min:</B>");
          snprintf(option, sizeof(option), "%s.%s", name,SCORE_FILTER _MIN);
          cgiMakeIntVarWithLimits(option, minVal, "Minimum score",0, minLimit,maxLimit);
          puts("<B>max:</B>");
          snprintf(option, sizeof(option), "%s.%s", name,SCORE_FILTER _MAX);
          cgiMakeIntVarWithLimits(option, maxVal, "Maximum score",0,minLimit,maxLimit);
          printf("(%d to %d)\n",minLimit,maxLimit);
          }
      else
          {
          printf("<b>Show only items with score at or above:</b> ");