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 "\"%s\"\n" //#define DEF_BUTTON "\"%s\"\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 "\"%s\"\n" #define DEF_BUTTON "\"%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 "help" int count = slCount(filterBySet); if(count == 1) puts(""); else printf("Filter items by: (select multiple categories and items - %s)
\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("
"); if(count == 1) printf("Filter by %s (select multiple items - %s)",filterBy->title,FILTERBY_HELP_LINK); else printf("%s",filterBy->title); printf("
\n"); // TODO: columnCount (Number of filterBoxes per row) should be configurable through tdb setting - #define FILTER_BY_FORMAT "
\n" - #else///ifndef NEW_JQUERY - #define FILTER_BY_FORMAT "
\n" + printf(FILTER_BY_FORMAT,ix,filterBy->htmlName); ix++; printf("All\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("
(%d to %d)",altLabel,minLimit, maxLimit); else if(minLimit != NO_VALUE) printf(" (minimum %d)",altLabel,minLimit); else if(maxLimit != NO_VALUE) printf(" (maximum %d)",altLabel,maxLimit); else printf(""); 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("
"); 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("
"); 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("
"); - 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("Filter score range: min:"); snprintf(option, sizeof(option), "%s.%s", name,SCORE_FILTER _MIN); cgiMakeIntVarWithLimits(option, minVal, "Minimum score",0, minLimit,maxLimit); puts("max:"); 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("Show only items with score at or above: ");