ff6ca2d3f51184034c9430ce91dd15773d2d661e
tdreszer
  Wed Oct 5 09:20:07 2011 -0700
More screw tightening.  Encode peaks are not configurable unless there are additional trackDb settings that say so.
diff --git src/hg/lib/hui.c src/hg/lib/hui.c
index defb9b3..942e1b4 100644
--- src/hg/lib/hui.c
+++ src/hg/lib/hui.c
@@ -4003,45 +4003,56 @@
     puts("<TBODY>");
     }
 
 // Finally the big "for loop" to list each subtrack as a table row.
 printf("\n<!-- ----- subtracks list ----- -->\n");
 for (subtrackRef = subtrackRefList; subtrackRef != NULL; subtrackRef = subtrackRef->next)
     {
     subtrack = subtrackRef->val;
     int ix;
 
     // Determine whether subtrack is checked, visible, configurable, has group membership, etc.
     int fourState = subtrackFourStateChecked(subtrack,cart);
     boolean checkedCB = fourStateChecked(fourState);
     boolean enabledCB = fourStateEnabled(fourState);
     boolean visibleCB = fourStateVisible(fourState);
+    membership_t *membership = subgroupMembershipGet(subtrack);
     eCfgType cType = cfgTypeFromTdb(subtrack,FALSE);
     if (cType != cfgNone)
         {
     #ifdef SUBTRACK_CFG
         // Turn off configuring for certain track type or if explicitly turned off
         if (regexMatch(subtrack->track, "^snp[0-9]+")     // Special cases to be removed
         ||  regexMatch(subtrack->track, "^cons[0-9]+way") // (matches logic in json setup in imageV2.c)
         ||  regexMatch(subtrack->track, "^multiz")
         ||  SETTING_IS_OFF(trackDbSettingClosestToHome(subtrack, "configureByPopup")))
+            cType = cfgNone;
+        else if (membersForAll->members[dimV])
+            {
+            if (-1 != (ix = stringArrayIx(membersForAll->members[dimV]->groupTag, membership->subgroups, membership->count)))
+                {  // Don't make a configurable subtrack if there is only one in the view (assumes view is configurable)
+                if (slCount(membersForAll->members[dimV]->subtrackList[ix]) < 2)
+                    cType = cfgNone;
+                }
+            }
+        else if (slCount(parentTdb->subtracks) < 2 && cfgTypeFromTdb(parentTdb,FALSE) != cfgNone)
+            cType = cfgNone;  // don't bother if there is a single subtrack but the composite is configurable.
     #else///ifndef SUBTRACK_CFG
         if (trackDbSettingClosestToHomeOn(subtrack, "configurable") == FALSE)
-    #endif///ndef SUBTRACK_CFG
             cType = cfgNone;
+    #endif///ndef SUBTRACK_CFG
         }
-    membership_t *membership = subgroupMembershipGet(subtrack);
 
     if (sortOrder == NULL && !useDragAndDrop)
         {
         if ( divisionIfNeeded(lastDivide,dividers,membership) )
             colorIx = (colorIx == COLOR_BG_DEFAULT_IX ? COLOR_BG_ALTDEFAULT_IX : COLOR_BG_DEFAULT_IX);
         }
 
     // Start the TR which must have an id that is directly related to the checkBox id
     char *id = checkBoxIdMakeForTrack(subtrack,membersForAll->members,membersForAll->dimMax,membership); // view is known tag
 
     printf("<TR valign='top' class='%s%s'",colors[colorIx],(useDragAndDrop?" trDraggable":""));
     printf(" id=tr_%s%s>\n",id,(!visibleCB && !displayAll?" style='display:none'":""));
 
     // Now the TD that holds the checkbox
     printf("<TD%s%s>",
@@ -4801,49 +4812,48 @@
             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;
 }
 
 
-#ifdef ALL_SCORE_FILTERS_LOGIC
 static int numericFiltersShowAll(struct cart *cart, struct trackDb *tdb, boolean *opened, boolean boxed,
                                boolean compositeLevel,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 slPair *extras = NULL;
     char *extraFields = trackDbSetting(tdb, "extraFields");  // TODo: seems like there should be a cleaner way
     if (extraFields != NULL)
         extras = slPairListFromString(extraFields,TRUE); // Quoted strings may be okay
 
     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
             {
             char *field = cloneString(filter->name);
             int ix = strlen(field) - strlen("Filter");
             assert(ix > 0);
             field[ix] = '\0';
             // Could lookup extraFields  // TODO: Should we be using extra fields?  Could this be sorted by the order in extraFields?
             if (extras != NULL)
                 {
                 char *foundLabel = slPairFindVal(extras, field);
                 if (foundLabel != NULL)
                     { // Found label so replace field
                     freeMem(field);
                     field = strchr(foundLabel,']');
                     if (field == NULL)
                         field = cloneString(foundLabel);
@@ -4856,69 +4866,64 @@
             safef(label,sizeof(label),"Minimum %s",field);
             freeMem(field);
             // Determine floating point or integer
             char *setting = trackDbSetting(tdb, filter->name);
             boolean isFloat = (strchr(setting,'.') != NULL);
             showScoreFilter(cart,tdb,opened,boxed,compositeLevel,name,title,label,filter->name,isFloat);
             count++;
             }
         slNameFree(&filter);
         }
     }
 if (count > 0)
     puts("</TABLE>");
 return count;
 }
-#endif///def ALL_SCORE_FILTERS_LOGIC
 
 
 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 skipScoreFilter = FALSE;
 filterBy_t *filterBySet = filterBySetGet(tdb,cart,name);
 
-#ifdef ALL_SCORE_FILTERS_LOGIC
 // Numeric filters are first
 boolean isBoxOpened = FALSE;
 if (numericFiltersShowAll(cart, tdb, &isBoxOpened, boxed, compositeLevel, name, title) > 0)
     skipScoreFilter = TRUE;
-#endif///def ALL_SCORE_FILTERS_LOGIC
 
 // Add any multi-selects next
 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(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);
@@ -5262,31 +5267,30 @@
         {
         if((int)max == NO_VALUE || ((int)maxLimit != NO_VALUE && maxLimit == max))
             dyStringPrintf(extraWhere, "%s(%s >= %g)", (*and?" and ":""),field,min);  // min only
         else if((int)min == NO_VALUE || ((int)minLimit != NO_VALUE && minLimit == min))
             dyStringPrintf(extraWhere, "%s(%s <= %g)", (*and?" and ":""),field,max);  // max only
         else
             dyStringPrintf(extraWhere, "%s(%s BETWEEN %g and %g)", (*and?" and ":""),field,min,max); // both min and max
 #endif//ndef FILTER_ASSUMES_RANGE_AT_LIMITS_IS_VALID_FILTER
         *and=TRUE;
         }
     }
     //if(dyStringLen(extraWhere)) warn("SELECT FROM %s WHERE %s",tdb->table,dyStringContents(extraWhere));
 return extraWhere;
 }
 
-#ifdef ALL_SCORE_FILTERS_LOGIC
 struct dyString *dyAddAllScoreFilters(struct cart *cart, struct trackDb *tdb, struct dyString *extraWhere,boolean *and)
 /* creates the where clause condition to gather together all random double filters
    Filters are expected to follow
         {fiterName}: trackDb min or min:max - default value(s);
         {filterName}Min or {filterName}: min (user supplied) cart variable;
         {filterName}Max: max (user supplied) cart variable;
         {filterName}Limits: trackDb allowed range "0.0:10.0" Optional
             uses:  defaultLimits: function param if no tdb limits settings found)
    The 'and' param and dyString in/out allows stringing multiple where clauses together */
 {
 struct slName *filterSettings = trackDbSettingsWildMatch(tdb, "*Filter");
 if (filterSettings)
     {
     struct slName *filter = NULL;
     while ((filter = slPopHead(&filterSettings)) != NULL)
@@ -5297,31 +5301,48 @@
             int ix = strlen(field) - strlen("filter");
             assert(ix > 0);
             field[ix] = '\0';
             char *setting = trackDbSetting(tdb, filter->name);
             // How to determine float or int ?  If actual tracDb setting has decimal places, then float!
             if (strchr(setting,'.') == NULL)
                 extraWhere = dyAddFilterAsInt(cart,tdb,extraWhere,filter->name,"0:1000",field,and);
             else
                 extraWhere = dyAddFilterAsDouble(cart,tdb,extraWhere,filter->name,NULL,field,and);
             }
         slNameFree(&filter);
         }
     }
 return extraWhere;
 }
-#endif///def ALL_SCORE_FILTERS_LOGIC
+
+boolean encodePeakHasCfgUi(struct trackDb *tdb)
+// Confirms that this track has encode Peak cfgUI
+{
+if (sameWord("narrowPeak",tdb->type)
+||  sameWord("broadPeak", tdb->type)
+||  sameWord("encodePeak",tdb->type)
+||  sameWord("gappedPeak",tdb->type))
+    {
+    return (trackDbSettingClosestToHome(tdb, SCORE_FILTER )
+        ||  trackDbSettingClosestToHome(tdb, SIGNAL_FILTER)
+        ||  trackDbSettingClosestToHome(tdb, PVALUE_FILTER)
+        ||  trackDbSettingClosestToHome(tdb, QVALUE_FILTER)
+        ||  trackDbSettingClosestToHome(tdb, SCORE_FILTER ));
+    }
+    return FALSE;
+}
+
 
 void encodePeakCfgUi(struct cart *cart, struct trackDb *tdb, char *name, char *title, boolean boxed)
 /* Put up UI for filtering wgEnocde peaks based on score, Pval and Qval */
 {
 boolean compositeLevel = isNameAtCompositeLevel(tdb,name);
 boolean opened = FALSE;
 showScoreFilter(cart,tdb,&opened,boxed,compositeLevel,name,title,"Minimum Signal value",     SIGNAL_FILTER,TRUE);
 showScoreFilter(cart,tdb,&opened,boxed,compositeLevel,name,title,"Minimum P-Value (<code>-log<sub>10</sub></code>)",PVALUE_FILTER,TRUE);
 showScoreFilter(cart,tdb,&opened,boxed,compositeLevel,name,title,"Minimum Q-Value (<code>-log<sub>10</sub></code>)",QVALUE_FILTER,TRUE);
 
 char *setting = trackDbSettingClosestToHomeOrDefault(tdb, SCORE_FILTER,NULL);//"0:1000");
 if(setting)
     {
     if(!opened)
         {