7bc24686024ec14d351ab208b5179ab251d7c463 tdreszer Fri Oct 14 16:34:15 2011 -0700 Major work on bedFilt, psl and wigMaf to make them properly composite ready. diff --git src/hg/lib/hui.c src/hg/lib/hui.c index d62ee79..5641573 100644 --- src/hg/lib/hui.c +++ src/hg/lib/hui.c @@ -1112,31 +1112,31 @@ BASE_COLOR_DRAW_OFF); stringVal = cartUsualStringClosestToHome(cart, tdb, FALSE, BASE_COLOR_VAR_SUFFIX,stringVal); return baseColorDrawOptStringToEnum(stringVal); } /*** Control of fancy indel display code: ***/ static boolean tdbOrCartBoolean(struct cart *cart, struct trackDb *tdb, char *settingName, char *defaultOnOff) /* Query cart & trackDb to determine if a boolean variable is set. */ { boolean alreadySet; alreadySet = !sameString("off",trackDbSettingOrDefault(tdb, settingName, defaultOnOff)); -alreadySet = cartUsualBooleanClosestToHome(cart, tdb, FALSE, settingName, alreadySet); // NOTE: compositeLevel=FALSE because tdb param already is at appropriate level +alreadySet = cartUsualBooleanClosestToHome(cart, tdb, FALSE, settingName, alreadySet); // NOTE: viewLevel=FALSE because tdb param already is at appropriate level return alreadySet; } static boolean indelAppropriate(struct trackDb *tdb) /* Return true if it makes sense to offer indel display options for tdb. */ { return (tdb && (startsWith("psl", tdb->type) || sameString("bam", tdb->type)) && (cfgOptionDefault("browser.indelOptions", NULL) != NULL)); } static void indelEnabledByName(struct cart *cart, struct trackDb *tdb, char *name, float basesPerPixel, boolean *retDoubleInsert, boolean *retQueryInsert, boolean *retPolyA) /* Query cart & trackDb to determine what indel display (if any) is enabled. Set * basesPerPixel to 0.0 to disable check for zoom level. */ @@ -1769,63 +1769,59 @@ void chimpDropDown(char *var, char *curVal) /* Make drop down of options. */ { cgiMakeDropList(var, chimpOptions, ArraySize(chimpOptions), curVal); } /****** Some stuff for mRNA and EST related controls *******/ static void addMrnaFilter(struct mrnaUiData *mud, char *track, char *label, char *key, char *table) /* Add an mrna filter */ { struct mrnaFilter *fil; -char buf[128]; AllocVar(fil); fil->label = label; -safef(buf, sizeof(buf), "%s_%s", track, key); -fil->key = cloneString(buf); +fil->suffix = cloneString(key); fil->table = table; slAddTail(&mud->filterList, fil); } -struct mrnaUiData *newBedUiData(char *track) +static struct mrnaUiData *newEmptyMrnaUiData(char *track) /* Make a new in extra-ui data structure for a bed. */ { struct mrnaUiData *mud; -char buf[128]; /* Expand me here */ AllocVar(mud); -safef(buf, sizeof(buf), "%sFt", track); -mud->filterTypeVar = cloneString(buf); -safef(buf, sizeof(buf), "%sLt", track); -mud->logicTypeVar = cloneString(buf); +mud->filterTypeSuffix = cloneString("Ft"); +mud->logicTypeSuffix = cloneString("Lt"); +return mud; +} + +struct mrnaUiData *newBedUiData(char *track) +/* Make a new in extra-ui data structure for a bed. */ +{ +struct mrnaUiData *mud = newEmptyMrnaUiData(track); addMrnaFilter(mud, track, "name", "name",track); return mud; } struct mrnaUiData *newMrnaUiData(char *track, boolean isXeno) /* Make a new in extra-ui data structure for mRNA. */ { -struct mrnaUiData *mud; -char buf[128]; -AllocVar(mud); -safef(buf, sizeof(buf), "%sFt", track); -mud->filterTypeVar = cloneString(buf); -safef(buf, sizeof(buf), "%sLt", track); -mud->logicTypeVar = cloneString(buf); +struct mrnaUiData *mud = newEmptyMrnaUiData(track); if (isXeno) addMrnaFilter(mud, track, "organism", "org", "organism"); addMrnaFilter(mud, track, "accession", "acc", "acc"); addMrnaFilter(mud, track, "author", "aut", "author"); addMrnaFilter(mud, track, "library", "lib", "library"); addMrnaFilter(mud, track, "tissue", "tis", "tissue"); addMrnaFilter(mud, track, "cell", "cel", "cell"); addMrnaFilter(mud, track, "keyword", "key", "keyword"); addMrnaFilter(mud, track, "gene", "gen", "geneName"); addMrnaFilter(mud, track, "product", "pro", "productName"); addMrnaFilter(mud, track, "description", "des", "description"); return mud; } int trackNameAndLabelCmp(const void *va, const void *vb) @@ -3326,32 +3322,32 @@ errAbort("filterBy values either all have labels (as value|label) or none do."); *chipper++ = 0; // The label is found inside the filters->svValues as the next string strSwapChar(chipper,'_',' '); // Title does not have underscores } else if (filterBy->valueAndLabel) errAbort("filterBy values either all have labels in form of value|label or none do."); } } slAddTail(&filterBySet,filterBy); // Keep them in order (only a few) if(cart != NULL) { char suffix[256]; safef(suffix, sizeof(suffix), "filterBy.%s", filterBy->column); - boolean compositeLevel = isNameAtCompositeLevel(tdb,name); - if(cartLookUpVariableClosestToHome(cart,tdb,compositeLevel,suffix,&(filterBy->htmlName))) + boolean viewLevel = isNameAtCompositeLevel(tdb,name); + if(cartLookUpVariableClosestToHome(cart,tdb,viewLevel,suffix,&(filterBy->htmlName))) filterBy->slChoices = cartOptionalSlNameList(cart,filterBy->htmlName); } if(filterBy->htmlName == NULL) { int len = strlen(name) + strlen(filterBy->column) + 15; filterBy->htmlName = needMem(len); safef(filterBy->htmlName, len, "%s.filterBy.%s", name,filterBy->column); } } freeMem(setting); return filterBySet; } void filterBySetFree(filterBy_t **filterBySet) @@ -3718,61 +3714,60 @@ { #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 + 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 there is only one subtrack + && 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 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; case cfgPeak: encodePeakCfgUi(cart,tdb,prefix,title,boxed); break; case cfgWig: wigCfgUi(cart,tdb,prefix,title,boxed); break; - case cfgWigMaf: // NOTE: wigMaf is using non-standard view level naming methods so isn't configurable by ajax - wigMafCfgUi(cart,tdb,prefix,title,boxed, db); + 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); break; - case cfgBedFilt: bedUi(tdb,cart,title, boxed); + case cfgBedFilt: bedFiltCfgUi(cart,tdb,prefix,title, boxed); break; #ifdef USE_BAM case cfgBam: bamCfgUi(cart, tdb, prefix, title, boxed); break; #endif 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) @@ -4505,77 +4500,119 @@ radioButton(filterTypeVar, filterTypeVal, "green"); radioButton(filterTypeVar, filterTypeVal, "blue"); radioButton(filterTypeVar, filterTypeVal, "exclude"); radioButton(filterTypeVar, filterTypeVal, "include"); if (none) radioButton(filterTypeVar, filterTypeVal, "none"); } void radioButton(char *var, char *val, char *ourVal) /* Print one radio button */ { cgiMakeRadioButton(var, ourVal, sameString(ourVal, val)); printf("%s ", ourVal); } -void oneMrnaFilterUi(struct controlGrid *cg, char *text, char *var, struct cart *cart) +void oneMrnaFilterUi(struct controlGrid *cg, struct trackDb *tdb, char *text, char *var, char *suffix, struct cart *cart) /* Print out user interface for one type of mrna filter. */ { controlGridStartCell(cg); printf("%s:<BR>", text); -cgiMakeTextVar(var, cartUsualString(cart, var, ""), 19); +boolean viewLevel = isNameAtCompositeLevel(tdb,var); +cgiMakeTextVar(var, cartUsualStringClosestToHome(cart, tdb, viewLevel,suffix, ""), 19); controlGridEndCell(cg); } -void bedUi(struct trackDb *tdb, struct cart *cart, char *title, boolean boxed) -/* Put up UI for an mRNA (or EST) track. */ +void bedFiltCfgUi(struct cart *cart, struct trackDb *tdb, char *prefix, char *title, boolean boxed) +/* Put up UI for an "bedFilter" tracks. */ { -struct mrnaUiData *mud = newBedUiData(tdb->track); +struct mrnaUiData *mud = newBedUiData(prefix); struct mrnaFilter *fil; struct controlGrid *cg = NULL; -char *filterTypeVar = mud->filterTypeVar; -char *filterTypeVal = cartUsualString(cart, filterTypeVar, "red"); +boolean viewLevel = isNameAtCompositeLevel(tdb,prefix); +char *filterTypeVal = cartUsualStringClosestToHome(cart, tdb, viewLevel, mud->filterTypeSuffix, "red"); boxed = cfgBeginBoxAndTitle(tdb, boxed, title); /* Define type of filter. */ printf("<table width=400><tr><td align='left'>\n"); -filterButtons(filterTypeVar, filterTypeVal, FALSE); +char buffer[256]; +safef(buffer, sizeof buffer,"%s.%s",prefix,mud->filterTypeSuffix); +filterButtons(buffer, filterTypeVal, FALSE); printf("</br>"); /* List various fields you can filter on. */ cg = startControlGrid(4, NULL); for (fil = mud->filterList; fil != NULL; fil = fil->next) - oneMrnaFilterUi(cg, fil->label, fil->key, cart); + { + safef(buffer, sizeof buffer,"%s.%s",prefix,fil->suffix); + oneMrnaFilterUi(cg, tdb, fil->label, buffer, fil->suffix, cart); + } endControlGrid(&cg); cfgEndBox(boxed); } +void mrnaCfgUi(struct cart *cart, struct trackDb *tdb, char *prefix, char *title, boolean boxed) +/* Put up UI for an mRNA (or EST) track. */ +{ +boolean isXeno = (sameString(tdb->track, "xenoMrna") || sameString(tdb->track, "xenoEst")); +struct mrnaUiData *mud = newMrnaUiData(prefix, isXeno); +struct mrnaFilter *fil; +struct controlGrid *cg = NULL; +boolean viewLevel = isNameAtCompositeLevel(tdb,prefix); +char *filterTypeVal = cartUsualStringClosestToHome(cart, tdb, viewLevel, mud->filterTypeSuffix,"red"); +char *logicTypeVal = cartUsualStringClosestToHome(cart, tdb, viewLevel, mud->logicTypeSuffix, "and"); + +boxed = cfgBeginBoxAndTitle(tdb, boxed, title); +/* Define type of filter. */ +char buffer[256]; +safef(buffer,sizeof buffer,"%s.%s",prefix,mud->filterTypeSuffix); +filterButtons(buffer, filterTypeVal, FALSE); +printf(" <B>Combination Logic:</B> "); +safef(buffer,sizeof buffer,"%s.%s",prefix,mud->logicTypeSuffix); +radioButton(buffer, logicTypeVal, "and"); +radioButton(buffer, logicTypeVal, "or"); +printf("<BR>\n"); + +/* List various fields you can filter on. */ +printf("<table border=0 cellspacing=1 cellpadding=1 width=%d>\n", CONTROL_TABLE_WIDTH); +cg = startControlGrid(4, NULL); +for (fil = mud->filterList; fil != NULL; fil = fil->next) + { + safef(buffer,sizeof buffer,"%s.%s",prefix,fil->suffix); + oneMrnaFilterUi(cg, tdb, fil->label, buffer, fil->suffix, cart); + } +endControlGrid(&cg); +baseColorDrawOptDropDown(cart, tdb); +indelShowOptions(cart, tdb); +cfgEndBox(boxed); +} + void scoreGrayLevelCfgUi(struct cart *cart, struct trackDb *tdb, char *prefix, int scoreMax) /* If scoreMin has been set, let user select the shade of gray for that score, in case * the default is too light to see or darker than necessary. */ { -boolean compositeLevel = isNameAtCompositeLevel(tdb,prefix); +boolean viewLevel = isNameAtCompositeLevel(tdb,prefix); char *scoreMinStr = trackDbSettingClosestToHome(tdb, GRAY_LEVEL_SCORE_MIN); if (scoreMinStr != NULL) { int scoreMin = atoi(scoreMinStr); // maxShade=9 taken from hgTracks/simpleTracks.c. Ignore the 10 in shadesOfGray[10+1] -- // maxShade is used to access the array. int maxShade = 9; int scoreMinGrayLevel = scoreMin * maxShade/scoreMax; if (scoreMinGrayLevel <= 0) scoreMinGrayLevel = 1; char *setting = trackDbSettingClosestToHome(tdb, MIN_GRAY_LEVEL); - int minGrayLevel = cartUsualIntClosestToHome(cart, tdb, compositeLevel, MIN_GRAY_LEVEL, + int minGrayLevel = cartUsualIntClosestToHome(cart, tdb, viewLevel, MIN_GRAY_LEVEL, setting ? atoi(setting) : scoreMinGrayLevel); if (minGrayLevel <= 0) minGrayLevel = 1; if (minGrayLevel > maxShade) minGrayLevel = maxShade; puts("\n<B>Shade of lowest-scoring items: </B>"); // Add javascript to select so that its color is consistent with option colors: int level = 255 - (255*minGrayLevel / maxShade); printf("<SELECT NAME=\"%s.%s\" STYLE='color: #%02x%02x%02x' class='normalText'", prefix, MIN_GRAY_LEVEL, level, level, level); int i; #ifdef OMIT // IE works without this code and FF doesn't work with it. printf(" onchange=\"switch(this.value) {"); for (i = 1; i < maxShade; i++) { level = 255 - (255*i / maxShade); @@ -4661,205 +4698,205 @@ { if(min && *min == NULL && minLoc != NULL) *min=minLoc; else freeMem(minLoc); if(max && *max == NULL && maxLoc != NULL) *max=maxLoc; else freeMem(maxLoc); return TRUE; } } return FALSE; } -static void getScoreIntRangeFromCart(struct cart *cart, struct trackDb *tdb, char *scoreName, - int *limitMin, int *limitMax,int *min,int *max) +static void getScoreIntRangeFromCart(struct cart *cart, struct trackDb *tdb, boolean viewLimit, + char *scoreName, int *limitMin, int *limitMax,int *min,int *max) /* gets an integer score range from the cart, but the limits from trackDb for any of the pointers provided, will return a value found, if found, else it's contents are undisturbed (use NO_VALUE to recognize unavaliable values) */ { char scoreLimitName[128]; char *deMin=NULL,*deMax=NULL; if((limitMin || limitMax) && getScoreLimitsFromTdb(tdb,scoreName,NULL,&deMin,&deMax)) { if(deMin != NULL && limitMin) *limitMin = atoi(deMin); if(deMax != NULL && limitMax) *limitMax = atoi(deMax); freeMem(deMin); freeMem(deMax); } if((min || max) && getScoreDefaultsFromTdb(tdb,scoreName,NULL,&deMin,&deMax)) { if(deMin != NULL && min) *min = atoi(deMin); if(deMax != NULL && max) *max =atoi(deMax); freeMem(deMin); freeMem(deMax); } if(max) { safef(scoreLimitName, sizeof(scoreLimitName), "%s%s", scoreName, _MAX); - deMax = cartOptionalStringClosestToHome(cart, tdb,FALSE,scoreLimitName); + deMax = cartOptionalStringClosestToHome(cart, tdb,viewLimit,scoreLimitName); if(deMax != NULL) *max = atoi(deMax); } if(min) { safef(scoreLimitName, sizeof(scoreLimitName), "%s%s", scoreName, (max && deMax? _MIN:"")); // Warning: name changes if max! - deMin = cartOptionalStringClosestToHome(cart, tdb,FALSE,scoreLimitName); + deMin = cartOptionalStringClosestToHome(cart, tdb,viewLimit,scoreLimitName); if(deMin != NULL) *min = atoi(deMin); } // Defaulting min and max within limits. Sorry for the horizontal ifs, but stacking the group makes them easier to follow if (min && limitMin && *limitMin != NO_VALUE && (*min == NO_VALUE || *min < *limitMin)) *min = *limitMin; if (min && limitMax && *limitMax != NO_VALUE && *min > *limitMax) *min = *limitMax; if (max && limitMax && *limitMax != NO_VALUE && (*max == NO_VALUE || *max > *limitMax)) *max = *limitMax; if (max && limitMin && *limitMin != NO_VALUE && *max < *limitMin) *max = *limitMin; } -static void getScoreFloatRangeFromCart(struct cart *cart, struct trackDb *tdb, char *scoreName, - double *limitMin,double *limitMax,double*min,double*max) +static void getScoreFloatRangeFromCart(struct cart *cart, struct trackDb *tdb, boolean viewLevel, + char *scoreName, double *limitMin,double *limitMax,double*min,double*max) /* gets an double score range from the cart, but the limits from trackDb for any of the pointers provided, will return a value found, if found, else it's contents are undisturbed (use NO_VALUE to recognize unavaliable values) */ { char scoreLimitName[128]; char *deMin=NULL,*deMax=NULL; if((limitMin || limitMax) && getScoreLimitsFromTdb(tdb,scoreName,NULL,&deMin,&deMax)) { if(deMin != NULL && limitMin) *limitMin = strtod(deMin,NULL); if(deMax != NULL && limitMax) *limitMax =strtod(deMax,NULL); freeMem(deMin); freeMem(deMax); } if((min || max) && getScoreDefaultsFromTdb(tdb,scoreName,NULL,&deMin,&deMax)) { if(deMin != NULL && min) *min = strtod(deMin,NULL); if(deMax != NULL && max) *max =strtod(deMax,NULL); freeMem(deMin); freeMem(deMax); } if(max) { safef(scoreLimitName, sizeof(scoreLimitName), "%s%s", scoreName, _MAX); - deMax = cartOptionalStringClosestToHome(cart, tdb,FALSE,scoreLimitName); + deMax = cartOptionalStringClosestToHome(cart, tdb,viewLevel,scoreLimitName); if(deMax != NULL) *max = strtod(deMax,NULL); } if(min) { safef(scoreLimitName, sizeof(scoreLimitName), "%s%s", scoreName, _MIN); // name is always {filterName}Min - deMin = cartOptionalStringClosestToHome(cart, tdb,FALSE,scoreLimitName); + deMin = cartOptionalStringClosestToHome(cart, tdb,viewLevel,scoreLimitName); if(deMin != NULL) *min = strtod(deMin,NULL); } // Defaulting min and max within limits. Sorry for the horizontal ifs, but stacking the group makes them easier to follow if (min && limitMin && (int)(*limitMin) != NO_VALUE && ((int)(*min) == NO_VALUE || *min < *limitMin)) *min = *limitMin; if (min && limitMax && (int)(*limitMax) != NO_VALUE && *min > *limitMax) *min = *limitMax; if (max && limitMax && (int)(*limitMax) != NO_VALUE && ((int)(*max) == NO_VALUE || *max > *limitMax)) *max = *limitMax; if (max && limitMin && (int)(*limitMin) != NO_VALUE && *max < *limitMin) *max = *limitMin; } static boolean showScoreFilter(struct cart *cart, struct trackDb *tdb, boolean *opened, boolean boxed, - boolean compositeLevel,char *name, char *title, char *label, + boolean viewLevel,char *name, char *title, char *label, char *scoreName, boolean isFloat) /* Shows a score filter control with minimum value and optional range */ { char *setting = trackDbSetting(tdb, scoreName); if(setting) { if(*opened == FALSE) { boxed = cfgBeginBoxAndTitle(tdb, boxed, title); puts("<TABLE>"); *opened = TRUE; } printf("<TR><TD align='right'><B>%s:</B><TD align='left'>",label); char varName[256]; char altLabel[256]; safef(varName, sizeof(varName), "%s%s", scoreName, _BY_RANGE); boolean filterByRange = trackDbSettingClosestToHomeOn(tdb, varName); // NOTE: could determine isFloat = (strchr(setting,'.') != NULL); However, historical trackDb settings of pValueFilter did not always contain '.' if (isFloat) { double minLimit=NO_VALUE,maxLimit=NO_VALUE; double minVal=minLimit,maxVal=maxLimit; colonPairToDoubles(setting,&minVal,&maxVal); - getScoreFloatRangeFromCart(cart,tdb,scoreName,&minLimit,&maxLimit,&minVal,&maxVal); + getScoreFloatRangeFromCart(cart,tdb,viewLevel,scoreName,&minLimit,&maxLimit,&minVal,&maxVal); safef(varName, sizeof(varName), "%s.%s%s", name, scoreName, _MIN); safef(altLabel, sizeof(altLabel), "%s%s", (filterByRange?"Minimum ":""), htmlEncodeText(htmlTextStripTags(label),FALSE)); cgiMakeDoubleVarWithLimits(varName,minVal, altLabel, 0,minLimit, maxLimit); if(filterByRange) { printf("<TD align='left'>to<TD align='left'>"); safef(varName, sizeof(varName), "%s.%s%s", name, scoreName, _MAX); safef(altLabel, sizeof(altLabel), "%s%s", (filterByRange?"Maximum ":""), label); cgiMakeDoubleVarWithLimits(varName,maxVal, altLabel, 0,minLimit, maxLimit); } safef(altLabel, sizeof(altLabel), "%s", (filterByRange?"": "colspan=3")); if(minLimit != NO_VALUE && maxLimit != NO_VALUE) printf("<TD align='left'%s> (%g to %g)",altLabel,minLimit, maxLimit); else if(minLimit != NO_VALUE) printf("<TD align='left'%s> (minimum %g)",altLabel,minLimit); else if(maxLimit != NO_VALUE) printf("<TD align='left'%s> (maximum %g)",altLabel,maxLimit); else printf("<TD align='left'%s",altLabel); } else { int minLimit=NO_VALUE,maxLimit=NO_VALUE; int minVal=minLimit,maxVal=maxLimit; colonPairToInts(setting,&minVal,&maxVal); - getScoreIntRangeFromCart(cart,tdb,scoreName,&minLimit,&maxLimit,&minVal,&maxVal); + getScoreIntRangeFromCart(cart,tdb,viewLevel,scoreName,&minLimit,&maxLimit,&minVal,&maxVal); safef(varName, sizeof(varName), "%s.%s%s", name, scoreName, filterByRange ? _MIN:""); safef(altLabel, sizeof(altLabel), "%s%s", (filterByRange?"Minimum ":""), label); cgiMakeIntVarWithLimits(varName,minVal, altLabel, 0,minLimit, maxLimit); if(filterByRange) { printf("<TD align='left'>to<TD align='left'>"); safef(varName, sizeof(varName), "%s.%s%s", name, scoreName, _MAX); safef(altLabel, sizeof(altLabel), "%s%s", (filterByRange?"Maximum ":""), label); cgiMakeIntVarWithLimits(varName,maxVal, altLabel, 0,minLimit, maxLimit); } safef(altLabel, sizeof(altLabel), "%s", (filterByRange?"": "colspan=3")); if(minLimit != NO_VALUE && maxLimit != NO_VALUE) 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, - 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 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) { @@ -4878,31 +4915,31 @@ freeMem(field); field = strchr(foundLabel,']'); if (field == NULL) field = cloneString(foundLabel); else field = cloneString(field + 1); strSwapChar(field,'_',' '); } } char label[128]; 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); + showScoreFilter(cart,tdb,opened,boxed,viewLevel,name,title,label,filter->name,isFloat); count++; } slNameFree(&filter); } } if (count > 0) puts("</TABLE>"); return count; } boolean bedScoreHasCfgUi(struct trackDb *tdb) // Confirms that this track has a bedScore Cfg UI { // Assumes that cfgType == cfgBedScore @@ -4932,37 +4969,37 @@ 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; filterBy_t *filterBySet = filterBySetGet(tdb,cart,name); // Numeric filters are first boolean isBoxOpened = FALSE; -if (numericFiltersShowAll(cart, tdb, &isBoxOpened, boxed, compositeLevel, name, title) > 0) +if (numericFiltersShowAll(cart, tdb, &isBoxOpened, boxed, viewLevel, name, title) > 0) skipScoreFilter = TRUE; // 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; } @@ -4974,31 +5011,31 @@ cfgEndBox(boxed); 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 (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> "); @@ -5012,40 +5049,40 @@ if (glvlScoreMin) scoreGrayLevelCfgUi(cart, tdb, name, maxScore); /* filter top-scoring N items in track */ char *scoreCtString = trackDbSettingClosestToHome(tdb, "filterTopScorers"); if (scoreCtString != NULL) { /* show only top-scoring items. This option only displayed if trackDb * setting exists. Format: filterTopScorers <on|off> <count> <table> */ char *words[2]; char *scoreFilterCt = NULL; chopLine(cloneString(scoreCtString), words); safef(option, sizeof(option), "%s.filterTopScorersOn", name); bool doScoreCtFilter = - cartUsualBooleanClosestToHome(cart, tdb, compositeLevel, "filterTopScorersOn", sameString(words[0], "on")); + cartUsualBooleanClosestToHome(cart, tdb, viewLevel, "filterTopScorersOn", sameString(words[0], "on")); puts("<P>"); cgiMakeCheckBox(option, doScoreCtFilter); safef(option, sizeof(option), "%s.filterTopScorersCt", name); - scoreFilterCt = cartUsualStringClosestToHome(cart, tdb, compositeLevel, "filterTopScorersCt", words[1]); + scoreFilterCt = cartUsualStringClosestToHome(cart, tdb, viewLevel, "filterTopScorersCt", words[1]); puts(" <B> Show only items in top-scoring </B>"); cgiMakeIntVarWithLimits(option,atoi(scoreFilterCt),"Top-scoring count",0,1,100000); /* Only check size of table if track does not have subtracks */ - if ( !compositeLevel && hTableExists(db, tdb->table)) + if ( !viewLevel && hTableExists(db, tdb->table)) printf(" (range: 1 to 100,000 total items: %d)\n",getTableSize(db, tdb->table)); else printf(" (range: 1 to 100,000)\n"); } cfgEndBox(boxed); } // Moved from hgTrackUi for consistency static void filterByChromCfgUi(struct cart *cart, struct trackDb *tdb) { char *filterSetting; char filterVar[256]; char *filterVal = ""; printf("<p><b>Filter by chromosome (e.g. chr10):</b> "); @@ -5084,94 +5121,94 @@ char *words[8]; int wordCount = wordCount = chopLine(typeLine, words); if (wordCount == 3 && sameWord(words[1], "xeno")) crossSpeciesCfgUi(cart,tdb); baseColorDropLists(cart, tdb, name); indelShowOptionsWithName(cart, tdb, name); cfgEndBox(boxed); } void netAlignCfgUi(char *db, struct cart *cart, struct trackDb *tdb, char *prefix, char *title, boolean boxed) /* Put up UI for net tracks */ { boxed = cfgBeginBoxAndTitle(tdb, boxed, title); -boolean compositeLevel = isNameAtCompositeLevel(tdb,prefix); +boolean viewLevel = isNameAtCompositeLevel(tdb,prefix); -enum netColorEnum netColor = netFetchColorOption(cart, tdb, compositeLevel); +enum netColorEnum netColor = netFetchColorOption(cart, tdb, viewLevel); char optString[256]; /* our option strings here */ safef(optString, ArraySize(optString), "%s.%s", prefix, NET_COLOR ); printf("<p><b>Color nets by: </b>"); netColorDropDown(optString, netColorEnumToString(netColor)); #ifdef NOT_YET -enum netLevelEnum netLevel = netFetchLevelOption(cart, tdb, compositeLevel); +enum netLevelEnum netLevel = netFetchLevelOption(cart, tdb, viewLevel); safef( optString, ArraySize(optString), "%s.%s", prefix, NET_LEVEL ); printf("<p><b>Limit display of nets to: </b>"); netLevelDropDown(optString, netLevelEnumToString(netLevel)); #endif cfgEndBox(boxed); } void chainCfgUi(char *db, struct cart *cart, struct trackDb *tdb, char *prefix, char *title, boolean boxed, char *chromosome) /* Put up UI for chain tracks */ { boxed = cfgBeginBoxAndTitle(tdb, boxed, title); -boolean compositeLevel = isNameAtCompositeLevel(tdb,prefix); +boolean viewLevel = isNameAtCompositeLevel(tdb,prefix); enum chainColorEnum chainColor = - chainFetchColorOption(cart, tdb, compositeLevel); + chainFetchColorOption(cart, tdb, viewLevel); /* check if we have normalized scores available */ boolean normScoreAvailable = chainDbNormScoreAvailable(tdb); char optString[256]; if (normScoreAvailable) { safef(optString, ArraySize(optString), "%s.%s", prefix, OPT_CHROM_COLORS ); printf("<p><b>Color chains by: </b>"); chainColorDropDown(optString, chainColorEnumToString(chainColor)); } else { printf("<p><b>Color track based on chromosome:</b> "); char optString[256]; /* initial value of chromosome coloring option is "on", unless * overridden by the colorChromDefault setting in the track */ char *binaryColorDefault = trackDbSettingClosestToHomeOrDefault(tdb, "colorChromDefault", "on"); /* allow cart to override trackDb setting */ safef(optString, sizeof(optString), "%s.color", prefix); char * colorSetting = cartUsualStringClosestToHome(cart, tdb, - compositeLevel, "color", binaryColorDefault); + viewLevel, "color", binaryColorDefault); cgiMakeRadioButton(optString, "on", sameString(colorSetting, "on")); printf(" on "); cgiMakeRadioButton(optString, "off", sameString(colorSetting, "off")); printf(" off "); printf("<br>\n"); } printf("<p><b>Filter by chromosome (e.g. chr10):</b> "); safef(optString, ArraySize(optString), "%s.%s", prefix, OPT_CHROM_FILTER); cgiMakeTextVar(optString, - cartUsualStringClosestToHome(cart, tdb, compositeLevel, + cartUsualStringClosestToHome(cart, tdb, viewLevel, OPT_CHROM_FILTER, ""), 15); if (normScoreAvailable) scoreCfgUi(db, cart,tdb,prefix,NULL,CHAIN_SCORE_MAXIMUM,FALSE); cfgEndBox(boxed); } struct dyString *dyAddFilterAsInt(struct cart *cart, struct trackDb *tdb, struct dyString *extraWhere,char *filter,char *defaultLimits, char*field, boolean *and) /* creates the where clause condition to support numeric int filter range. 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; @@ -5189,31 +5226,31 @@ if(trackDbSettingClosestToHome(tdb, filterLimitName) != NULL) return extraWhere; char *setting = NULL; if(differentWord(filter,SCORE_FILTER)) setting = trackDbSettingClosestToHome(tdb, filter); else setting = trackDbSettingClosestToHomeOrDefault(tdb, filter,"0:1000"); if(setting || sameWord(filter,NO_SCORE_FILTER)) { boolean invalid = FALSE; int minValueTdb = 0,maxValueTdb = NO_VALUE; colonPairToInts(setting,&minValueTdb,&maxValueTdb); int minLimit=NO_VALUE,maxLimit=NO_VALUE,min=minValueTdb,max=maxValueTdb; colonPairToInts(defaultLimits,&minLimit,&maxLimit); - getScoreIntRangeFromCart(cart,tdb,filter,&minLimit,&maxLimit,&min,&max); + getScoreIntRangeFromCart(cart,tdb,FALSE,filter,&minLimit,&maxLimit,&min,&max); if(minLimit != NO_VALUE || maxLimit != NO_VALUE) { // assume tdb default values within range! (don't give user errors that have no consequence) if((min != minValueTdb && ((minLimit != NO_VALUE && min < minLimit) || (maxLimit != NO_VALUE && min > maxLimit))) || (max != maxValueTdb && ((minLimit != NO_VALUE && max < minLimit) || (maxLimit != NO_VALUE && max > maxLimit)))) { invalid = TRUE; char value[64]; if(max == NO_VALUE) // min only is allowed, but max only is not safef(value, sizeof(value), "entered minimum (%d)", min); else safef(value, sizeof(value), "entered range (min:%d and max:%d)", min, max); char limits[64]; @@ -5269,31 +5306,31 @@ {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 */ { char *setting = trackDbSettingClosestToHome(tdb, filter); if(setting) { boolean invalid = FALSE; double minValueTdb = 0,maxValueTdb = NO_VALUE; colonPairToDoubles(setting,&minValueTdb,&maxValueTdb); double minLimit=NO_VALUE,maxLimit=NO_VALUE,min=minValueTdb,max=maxValueTdb; colonPairToDoubles(defaultLimits,&minLimit,&maxLimit); - getScoreFloatRangeFromCart(cart,tdb,filter,&minLimit,&maxLimit,&min,&max); + getScoreFloatRangeFromCart(cart,tdb,FALSE,filter,&minLimit,&maxLimit,&min,&max); if((int)minLimit != NO_VALUE || (int)maxLimit != NO_VALUE) { // assume tdb default values within range! (don't give user errors that have no consequence) if((min != minValueTdb && (((int)minLimit != NO_VALUE && min < minLimit) || ((int)maxLimit != NO_VALUE && min > maxLimit))) || (max != maxValueTdb && (((int)minLimit != NO_VALUE && max < minLimit) || ((int)maxLimit != NO_VALUE && max > maxLimit)))) { invalid = TRUE; char value[64]; if((int)max == NO_VALUE) // min only is allowed, but max only is not safef(value, sizeof(value), "entered minimum (%g)", min); else safef(value, sizeof(value), "entered range (min:%g and max:%g)", min, max); char limits[64]; @@ -5385,49 +5422,49 @@ || 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 viewLevel = 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); +showScoreFilter(cart,tdb,&opened,boxed,viewLevel,name,title,"Minimum Signal value", SIGNAL_FILTER,TRUE); +showScoreFilter(cart,tdb,&opened,boxed,viewLevel,name,title,"Minimum P-Value (<code>-log<sub>10</sub></code>)",PVALUE_FILTER,TRUE); +showScoreFilter(cart,tdb,&opened,boxed,viewLevel,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) { boxed = cfgBeginBoxAndTitle(tdb, boxed, title); puts("<TABLE>"); opened = TRUE; } char varName[256]; int minLimit=0,maxLimit=1000,minVal=0,maxVal=NO_VALUE; colonPairToInts(setting,&minVal,&maxVal); - getScoreIntRangeFromCart(cart,tdb,SCORE_FILTER,&minLimit,&maxLimit,&minVal,&maxVal); + getScoreIntRangeFromCart(cart,tdb,viewLevel,SCORE_FILTER,&minLimit,&maxLimit,&minVal,&maxVal); if(maxVal != NO_VALUE) puts("<TR><TD align='right'><B>Score range: min:</B><TD align='left'>"); else puts("<TR><TD align='right'><B>Minimum score:</B><TD align='left'>"); safef(varName, sizeof(varName), "%s%s", SCORE_FILTER, _BY_RANGE); boolean filterByRange = trackDbSettingClosestToHomeOn(tdb, varName); safef(varName, sizeof(varName), "%s.%s%s", name, SCORE_FILTER, (filterByRange?_MIN:"")); cgiMakeIntVarWithLimits(varName, minVal, "Minimum score", 0, minLimit, maxLimit); if(filterByRange) { if(maxVal == NO_VALUE) maxVal = maxLimit; puts("<TD align='right'>to<TD align='left'>"); safef(varName, sizeof(varName), "%s.%s%s", name, SCORE_FILTER,_MAX); cgiMakeIntVarWithLimits(varName, maxVal, "Maximum score", 0, minLimit, maxLimit); @@ -5439,37 +5476,37 @@ scoreGrayLevelCfgUi(cart, tdb, name, 1000); puts("</TR>"); } } if(opened) { puts("</TABLE>"); cfgEndBox(boxed); } } void genePredCfgUi(struct cart *cart, struct trackDb *tdb, char *name, char *title, boolean boxed) /* Put up gencode-specific controls */ { char varName[64]; -boolean compositeLevel = isNameAtCompositeLevel(tdb,name); -char *geneLabel = cartUsualStringClosestToHome(cart, tdb,compositeLevel, "label", "gene"); +boolean viewLevel = isNameAtCompositeLevel(tdb,name); +char *geneLabel = cartUsualStringClosestToHome(cart, tdb,viewLevel, "label", "gene"); boxed = cfgBeginBoxAndTitle(tdb, boxed, title); if (sameString(name, "acembly")) { - char *acemblyClass = cartUsualStringClosestToHome(cart,tdb,compositeLevel,"type", acemblyEnumToString(0)); + char *acemblyClass = cartUsualStringClosestToHome(cart,tdb,viewLevel,"type", acemblyEnumToString(0)); printf("<p><b>Gene Class: </b>"); acemblyDropDown("acembly.type", acemblyClass); printf(" "); } else if(startsWith("wgEncodeGencode", name) || sameString("wgEncodeSangerGencode", name) || (startsWith("encodeGencode", name) && !sameString("encodeGencodeRaceFrags", name))) { printf("<B>Label:</B> "); safef(varName, sizeof(varName), "%s.label", name); cgiMakeRadioButton(varName, "gene", sameString("gene", geneLabel)); printf("%s ", "gene"); cgiMakeRadioButton(varName, "accession", sameString("accession", geneLabel)); printf("%s ", "accession"); cgiMakeRadioButton(varName, "both", sameString("both", geneLabel)); @@ -5494,161 +5531,130 @@ filterBy_t *filterBySet = filterBySetGet(tdb,cart,name); if(filterBySet != NULL) { printf("<BR>"); filterBySetCfgUi(cart,tdb,filterBySet,FALSE); filterBySetFree(&filterBySet); } cfgEndBox(boxed); } static boolean isSpeciesOn(struct cart *cart, struct trackDb *tdb, char *species, char *option, int optionSize, boolean defaultState) /* check the cart to see if species is turned off or on (default is defaultState) */ { -#ifdef SUBTRACK_CFG - // FIXME: works now in configByAjax but affects not seen in track image!!! -boolean compositeLevel = isNameAtCompositeLevel(tdb,option); +boolean viewLevel = isNameAtCompositeLevel(tdb,option); if (*option == '\0') safef(option, optionSize, "%s.%s", tdb->track, species); else { char *suffix = option + strlen(option); int suffixSize = optionSize - strlen(option); safef(suffix,suffixSize,".%s",species); } -return cartUsualBooleanClosestToHome(cart,tdb, compositeLevel, species,defaultState); -#else///ifndef SUBTRACK_CFG -boolean ret = defaultState; -safef(option, optionSize, "%s.%s", tdb->track, species); - -/* see if this is a simple multiz (not composite track) */ -char *s = cartOptionalString(cart, option); -if (s != NULL) - ret = (sameString(s, "on") || atoi(s) > 0); -else - { - /* check parent to see if it has these variables */ - if (tdb->parent != NULL) - { - char *viewString; - if (subgroupFind(tdb, "view", &viewString)) - { - safef(option, optionSize, "%s.%s.%s", - tdb->parent->track, viewString, species); - ret = cartUsualBoolean(cart, option, ret); - } - } - } - -return ret; -#endif///ndef SUBTRACK_CFG +return cartUsualBooleanClosestToHome(cart,tdb, viewLevel, species,defaultState); } -char **wigMafGetSpecies(struct cart *cart, struct trackDb *tdb, char *db, struct wigMafSpecies **list, int *groupCt) +char **wigMafGetSpecies(struct cart *cart, struct trackDb *tdb, char *prefix, char *db, struct wigMafSpecies **list, int *groupCt) { int speciesCt = 0; -char *speciesGroup = trackDbSettingClosestToHome(tdb, SPECIES_GROUP_VAR); -char *speciesUseFile = trackDbSettingClosestToHome(tdb, SPECIES_USE_FILE); -char *speciesOrder = trackDbSettingClosestToHome(tdb, SPECIES_ORDER_VAR); +char *speciesGroup = trackDbSetting(tdb, SPECIES_GROUP_VAR); +char *speciesUseFile = trackDbSetting(tdb, SPECIES_USE_FILE); +char *speciesOrder = trackDbSetting(tdb, SPECIES_ORDER_VAR); char sGroup[24]; //Ochar *groups[20]; struct wigMafSpecies *wmSpecies, *wmSpeciesList = NULL; int group; int i; #define MAX_SP_SIZE 2000 #define MAX_GROUPS 20 char *species[MAX_SP_SIZE]; char option[MAX_SP_SIZE]; /* determine species and groups for pairwise -- create checkboxes */ if (speciesOrder == NULL && speciesGroup == NULL && speciesUseFile == NULL) { if (isCustomTrack(tdb->track)) return NULL; errAbort("Track %s missing required trackDb setting: speciesOrder, speciesGroups, or speciesUseFile", tdb->track); } char **groups = needMem(MAX_GROUPS * sizeof (char *)); *groupCt = 1; if (speciesGroup) *groupCt = chopByWhite(speciesGroup, groups, MAX_GROUPS); if (speciesUseFile) { if ((speciesGroup != NULL) || (speciesOrder != NULL)) errAbort("Can't specify speciesUseFile and speciesGroup or speciesOrder"); - speciesOrder = cartGetOrderFromFile(db, cart, speciesUseFile); - } + speciesOrder = cartGetOrderFromFile(db, cart, speciesUseFile); // Not sure why this is in cart + } // not tdb based so no ClosestToHome for (group = 0; group < *groupCt; group++) { if (*groupCt != 1 || !speciesOrder) { safef(sGroup, sizeof sGroup, "%s%s", SPECIES_GROUP_PREFIX, groups[group]); speciesOrder = trackDbRequiredSetting(tdb, sGroup); } speciesCt = chopLine(speciesOrder, species); for (i = 0; i < speciesCt; i++) { AllocVar(wmSpecies); wmSpecies->name = cloneString(species[i]); -#ifdef SUBTRACK_CFG - *option = '\0'; // signal to look for the lowest level -#endif///def SUBTRACK_CFG + safecpy(option,sizeof option,prefix); wmSpecies->on = isSpeciesOn(cart, tdb, wmSpecies->name, option, sizeof option, TRUE); wmSpecies->group = group; slAddHead(&wmSpeciesList, wmSpecies); } } slReverse(&wmSpeciesList); *list = wmSpeciesList; return groups; } struct wigMafSpecies * wigMafSpeciesTable(struct cart *cart, struct trackDb *tdb, char *name, char *db) { int groupCt; #define MAX_SP_SIZE 2000 char option[MAX_SP_SIZE]; int group, prevGroup; int i,j; +boolean viewLevel = isNameAtCompositeLevel(tdb,name); bool lowerFirstChar = TRUE; -char *speciesTarget = trackDbSetting(tdb, SPECIES_TARGET_VAR); -char *speciesTree = trackDbSetting(tdb, SPECIES_TREE_VAR); struct wigMafSpecies *wmSpeciesList; -char **groups = wigMafGetSpecies(cart, tdb, db, &wmSpeciesList, &groupCt); +char **groups = wigMafGetSpecies(cart, tdb, name, db, &wmSpeciesList, &groupCt); struct wigMafSpecies *wmSpecies = wmSpeciesList; struct slName *speciesList = NULL; for(; wmSpecies; wmSpecies = wmSpecies->next) { struct slName *newName = slNameNew(wmSpecies->name); slAddHead(&speciesList, newName); //printf("%s<BR>\n",speciesList->name); } slReverse(&speciesList); int numberPerRow; -struct phyloTree *tree; boolean lineBreakJustPrinted; char trackName[255]; char query[256]; char **row; struct sqlConnection *conn; struct sqlResult *sr; char *words[MAX_SP_SIZE]; int defaultOffSpeciesCnt = 0; if(cartOptionalString(cart, "ajax") == NULL) jsIncludeFile("utils.js",NULL); //jsInit(); puts("\n<P><B>Species selection:</B> "); PLUS_BUTTON( "id", "plus_pw","cb_maf_","_maf_"); @@ -5660,56 +5666,62 @@ char *defaultOffSpecies = trackDbSetting(tdb, "speciesDefaultOff"); struct hash *offHash = NULL; if (defaultOffSpecies) { offHash = newHash(5); DEFAULT_BUTTON( "id", "default_pw","cb_maf_","_maf_"); int wordCt = chopLine(defaultOffSpecies, words); defaultOffSpeciesCnt = wordCt; /* build hash of species that should be off */ int ii; for(ii=0; ii < wordCt; ii++) hashAdd(offHash, words[ii], NULL); } +#define BRANEY_SAYS_USETARG_IS_OBSOLETE +#ifndef BRANEY_SAYS_USETARG_IS_OBSOLETE +char *speciesTarget = trackDbSetting(tdb, SPECIES_TARGET_VAR); +char *speciesTree = trackDbSetting(tdb, SPECIES_TREE_VAR); +struct phyloTree *tree; if ((speciesTree != NULL) && ((tree = phyloParseString(speciesTree)) != NULL)) { char buffer[128]; char *nodeNames[512]; int numNodes = 0; char *path, *orgName; int ii; safef(buffer, sizeof(buffer), "%s.vis",name); - cartMakeRadioButton(cart, buffer,"useTarg", "useTarg"); + cartMakeRadioButton(cart, buffer,"useTarg", "useTarg");// not closestToHome because BRANEY_SAYS_USETARG_IS_OBSOLETE printf("Show shortest path to target species: "); path = phyloNodeNames(tree); numNodes = chopLine(path, nodeNames); for(ii=0; ii < numNodes; ii++) { if ((orgName = hOrganism(nodeNames[ii])) != NULL) nodeNames[ii] = orgName; nodeNames[ii][0] = toupper(nodeNames[ii][0]); } cgiMakeDropList(SPECIES_HTML_TARGET, nodeNames, numNodes, - cartUsualString(cart, SPECIES_HTML_TARGET, speciesTarget)); + cartUsualString(cart, SPECIES_HTML_TARGET, speciesTarget));// not closestToHome because BRANEY_SAYS_USETARG_IS_OBSOLETE puts("<br>"); - cartMakeRadioButton(cart,buffer,"useCheck", "useTarg"); + cartMakeRadioButton(cart,buffer,"useCheck", "useTarg"); // not closestToHome because BRANEY_SAYS_USETARG_IS_OBSOLETE printf("Show all species checked : "); } +#endif///ndef BRANEY_SAYS_USETARG_IS_OBSOLETE if (groupCt == 1) puts("\n<TABLE><TR>"); group = -1; lineBreakJustPrinted = FALSE; for (wmSpecies = wmSpeciesList, i = 0, j = 0; wmSpecies != NULL; wmSpecies = wmSpecies->next, i++) { char *label; prevGroup = group; group = wmSpecies->group; if (groupCt != 1 && group != prevGroup) { i = 0; j = 0; @@ -5771,180 +5783,168 @@ /* test if the entry actually is part of the specific maf track data */ if (chp != NULL) { *chp = '\0'; safef(query, sizeof(query), "select id from %sMsa where id = 'ss.%s'", trackName, label); conn = hAllocConn(db); sr = sqlGetResult(conn, query); row = sqlNextRow(sr); /* offer it only if the entry is found in current maf data set */ if (row != NULL) { puts("<TD>"); - cgiMakeCheckBoxWithId(option, cartUsualBoolean(cart, option, checked),id); + cgiMakeCheckBoxWithId(option,cartUsualBooleanClosestToHome( + cart, tdb, viewLevel,wmSpecies->name, checked),id); printf ("%s", label); puts("</TD>"); fflush(stdout); lineBreakJustPrinted = FALSE; j++; } sqlFreeResult(&sr); hFreeConn(&conn); } } else { puts("<TD>"); boolean defaultState = TRUE; if (offHash != NULL) defaultState = (hashLookup(offHash, wmSpecies->name) == NULL); -#ifdef SUBTRACK_CFG safecpy(option, sizeof(option), name); -#endif///def SUBTRACK_CFG wmSpecies->on = isSpeciesOn(cart, tdb, wmSpecies->name, option, sizeof option, defaultState ); cgiMakeCheckBoxWithId(option, wmSpecies->on,id); label = hOrganism(wmSpecies->name); if (label == NULL) label = wmSpecies->name; if (lowerFirstChar) *label = tolower(*label); printf ("%s<BR>", label); puts("</TD>"); lineBreakJustPrinted = FALSE; j++; } } puts("</TR></TABLE><BR>\n"); return wmSpeciesList; } void wigMafCfgUi(struct cart *cart, struct trackDb *tdb,char *name, char *title, boolean boxed, char *db) /* UI for maf/wiggle track * NOTE: calls wigCfgUi */ { bool lowerFirstChar = TRUE; int i; char option[MAX_SP_SIZE]; -char *viewString = NULL; - -// FIXME: wigMaf is using non-standard view level naming methods so isn't configurable by ajax -#ifndef SUBTRACK_CFG -subgroupFind(tdb, "view", &viewString); -#endif///ndef SUBTRACK_CFG +boolean viewLevel = isNameAtCompositeLevel(tdb,name); boxed = cfgBeginBoxAndTitle(tdb, boxed, title); char *defaultCodonSpecies = trackDbSetting(tdb, SPECIES_CODON_DEFAULT); char *framesTable = trackDbSetting(tdb, "frames"); char *firstCase = trackDbSetting(tdb, ITEM_FIRST_CHAR_CASE); if (firstCase != NULL) { if (sameWord(firstCase, "noChange")) lowerFirstChar = FALSE; } char *treeImage = NULL; struct consWiggle *consWig, *consWiggles = wigMafWiggles(db, tdb); boolean isWigMafProt = FALSE; if (strstr(tdb->type, "wigMafProt")) isWigMafProt = TRUE; puts("<TABLE><TR><TD VALIGN=\"TOP\">"); if (consWiggles && consWiggles->next) { /* check for alternate conservation wiggles -- create checkboxes */ puts("<P STYLE=\"margin-top:10;\"><B>Conservation:</B>" ); boolean first = TRUE; for (consWig = consWiggles; consWig != NULL; consWig = consWig->next) { - char *wigVar = wigMafWiggleVar(tdb, consWig); - cgiMakeCheckBox(wigVar, cartUsualBoolean(cart, wigVar, first)); + char *wigVar = wigMafWiggleVar(name, consWig); + char *wigVarSuffix = wigVar + strlen(name) + 1; + cgiMakeCheckBox(wigVar, + cartUsualBooleanClosestToHome(cart, tdb, viewLevel, wigVarSuffix, first)); first = FALSE; subChar(consWig->uiLabel, '_', ' '); printf ("%s ", consWig->uiLabel); } } struct wigMafSpecies *wmSpeciesList = wigMafSpeciesTable(cart, tdb, name, db); struct wigMafSpecies *wmSpecies; if (isWigMafProt) puts("<B>Multiple alignment amino acid-level:</B><BR>" ); else puts("<B>Multiple alignment base-level:</B><BR>" ); -if (viewString != NULL) - safef(option, sizeof option, "%s.%s.%s", name, viewString, MAF_DOT_VAR); -else safef(option, sizeof option, "%s.%s", name, MAF_DOT_VAR); -cgiMakeCheckBox(option, cartCgiUsualBoolean(cart, option, FALSE)); +cgiMakeCheckBox(option, cartUsualBooleanClosestToHome(cart, tdb, viewLevel,MAF_DOT_VAR, FALSE)); if (isWigMafProt) puts("Display amino acids identical to reference as dots<BR>" ); else puts("Display bases identical to reference as dots<BR>" ); -if (viewString != NULL) - safef(option, sizeof option, "%s.%s.%s", name, viewString, MAF_CHAIN_VAR); -else safef(option, sizeof option, "%s.%s", name, MAF_CHAIN_VAR); -cgiMakeCheckBox(option, cartCgiUsualBoolean(cart, option, TRUE)); +cgiMakeCheckBox(option, cartUsualBooleanClosestToHome(cart, tdb, viewLevel, MAF_CHAIN_VAR, TRUE)); char *irowStr = trackDbSetting(tdb, "irows"); boolean doIrows = (irowStr == NULL) || !sameString(irowStr, "off"); if (isCustomTrack(tdb->track) || doIrows) puts("Display chains between alignments<BR>"); else { if (isWigMafProt) puts("Display unaligned amino acids with spanning chain as 'o's<BR>"); else puts("Display unaligned bases with spanning chain as 'o's<BR>"); } safef(option, sizeof option, "%s.%s", name, "codons"); if (framesTable) { char *nodeNames[512]; char buffer[128]; printf("<BR><B>Codon Translation:</B><BR>"); printf("Default species to establish reading frame: "); nodeNames[0] = db; for (wmSpecies = wmSpeciesList, i = 1; wmSpecies != NULL; wmSpecies = wmSpecies->next, i++) { nodeNames[i] = wmSpecies->name; } cgiMakeDropList(SPECIES_CODON_DEFAULT, nodeNames, i, - cartUsualString(cart, SPECIES_CODON_DEFAULT, defaultCodonSpecies)); + cartUsualString(cart, SPECIES_CODON_DEFAULT, defaultCodonSpecies)); // tdb independent var puts("<br>"); - if (viewString != NULL) - safef(buffer, sizeof(buffer), "%s.%s.codons",name, viewString); - else + char *cartVal = cartUsualStringClosestToHome(cart, tdb, viewLevel, "codons","codonDefault"); safef(buffer, sizeof(buffer), "%s.codons",name); - cartMakeRadioButton(cart, buffer,"codonNone", "codonDefault"); + cgiMakeRadioButton(buffer,"codonNone", sameWord(cartVal,"codonNone")); printf("No codon translation<BR>"); - cartMakeRadioButton(cart, buffer,"codonDefault", "codonDefault"); + cgiMakeRadioButton(buffer,"codonDefault", sameWord(cartVal,"codonDefault")); printf("Use default species reading frames for translation<BR>"); - cartMakeRadioButton(cart, buffer,"codonFrameNone", "codonDefault"); + cgiMakeRadioButton(buffer,"codonFrameNone",sameWord(cartVal,"codonFrameNone")); printf("Use reading frames for species if available, otherwise no translation<BR>"); - cartMakeRadioButton(cart, buffer,"codonFrameDef", "codonDefault"); + cgiMakeRadioButton(buffer,"codonFrameDef", sameWord(cartVal,"codonFrameDef")); printf("Use reading frames for species if available, otherwise use default species<BR>"); } else { /* Codon highlighting does not apply to wigMafProt type */ if (!strstr(tdb->type, "wigMafProt")) { puts("<P><B>Codon highlighting:</B><BR>" ); #ifdef GENE_FRAMING safef(option, sizeof(option), "%s.%s", name, MAF_FRAME_VAR); char *currentCodonMode = cartCgiUsualString(cart, option, MAF_FRAME_GENE); /* Disable codon highlighting */ @@ -6137,85 +6137,84 @@ { char *visibility = NULL; compositeViewCfgExpandedByDefault(parentTdb,view,&visibility); enum trackVisibility vis = hTvFromString(visibility); freeMem(visibility); return vis; } static boolean hCompositeDisplayViewDropDowns(char *db, struct cart *cart, struct trackDb *parentTdb) /* UI for composite view drop down selections. */ { int ix; char varName[SMALLBUF]; char classes[SMALLBUF]; char javascript[JBUFSIZE]; -#define CFG_LINK "<B><A HREF=\"#a_cfg_%s\" onclick=\"return (showConfigControls('%s') == false);\" title=\"%s Configuration\">%s</A><INPUT TYPE=HIDDEN NAME='%s.%s.showCfg' value='%s'></B>" -#define MAKE_CFG_LINK(name,title,tbl,open) printf(CFG_LINK, (name),(name),(title),(title),(tbl),(name),((open)?"on":"off")) +#define CFG_LINK "<B><A HREF=\"#a_cfg_%s\" onclick=\"return (showConfigControls('%s') == false);\" title=\"%s Configuration\">%s</A><INPUT TYPE=HIDDEN NAME='%s.showCfg' value='%s'></B>" +#define MAKE_CFG_LINK(name,title,viewTrack,open) printf(CFG_LINK, (name),(name),(title),(title),(viewTrack),((open)?"on":"off")) membersForAll_t *membersForAll = membersForAllSubGroupsGet(parentTdb, cart); // membersForAll is generated once per track, then cached members_t *membersOfView = membersForAll->members[dimV]; if(membersOfView == NULL) return FALSE; char configurable[membersOfView->count]; memset(configurable,cfgNone,sizeof(configurable)); int firstOpened = -1; boolean makeCfgRows = FALSE; struct trackDb **matchedViewTracks = needMem(sizeof(struct trackDb *)*membersOfView->count); for (ix = 0; ix < membersOfView->count; ix++) { - char *viewName = membersOfView->tags[ix]; if (membersOfView->subtrackList != NULL && membersOfView->subtrackList[ix] != NULL) { struct trackDb *subtrack = membersOfView->subtrackList[ix]->val; matchedViewTracks[ix] = subtrack->parent; configurable[ix] = (char)cfgTypeFromTdb(subtrack, TRUE); if(configurable[ix] != cfgNone) { if(firstOpened == -1) { - safef(varName, sizeof(varName), "%s.%s.showCfg", parentTdb->track, viewName); - if(cartUsualBoolean(cart,varName,FALSE)) + safef(varName, sizeof(varName), "%s.showCfg", matchedViewTracks[ix]->track); + if(cartUsualBoolean(cart,varName,FALSE)) // No need for closestToHome: view level input firstOpened = ix; } makeCfgRows = TRUE; } } } toLowerN(membersOfView->groupTitle, 1); printf("<B>Select %s</B> (<A HREF='../goldenPath/help/multiView.html' title='Help on views' TARGET=_BLANK>help</A>):\n", membersOfView->groupTitle); printf("<TABLE><TR style='text-align:left;'>\n"); // Make row of vis drop downs for (ix = 0; ix < membersOfView->count; ix++) { char *viewName = membersOfView->tags[ix]; if (matchedViewTracks[ix] != NULL) { printf("<TD>"); if(configurable[ix] != cfgNone) { - MAKE_CFG_LINK(membersOfView->tags[ix],membersOfView->titles[ix],parentTdb->track,(firstOpened == ix)); + MAKE_CFG_LINK(membersOfView->tags[ix],membersOfView->titles[ix],matchedViewTracks[ix]->track,(firstOpened == ix)); } else printf("<B>%s</B>",membersOfView->titles[ix]); puts("</TD>"); - safef(varName, sizeof(varName), "%s.%s.vis", parentTdb->track, viewName); + safef(varName, sizeof(varName), "%s.%s.vis", parentTdb->track, viewName); // FIXME: Time to get rid of "track.view.vis" since viewInTheMiddle enum trackVisibility tv = hTvFromString(cartUsualString(cart, varName,hStringFromTv(visCompositeViewDefault(parentTdb,viewName)))); safef(javascript, sizeof(javascript), "onchange=\"matSelectViewForSubTracks(this,'%s');\" onfocus='this.lastIndex=this.selectedIndex;'", viewName); printf("<TD>"); safef(classes, sizeof(classes), "viewDD normalText %s", membersOfView->tags[ix]); hTvDropDownClassWithJavascript(varName, tv, parentTdb->canPack,classes,javascript); puts(" </TD>"); } } puts("</TR>"); // Make row of cfg boxes if needed if(makeCfgRows) @@ -6224,37 +6223,36 @@ for (ix = 0; ix < membersOfView->count; ix++) { struct trackDb *view = matchedViewTracks[ix]; if (view != NULL) { char *viewName = membersOfView->tags[ix]; printf("<TR id=\"tr_cfg_%s\"", viewName); if((firstOpened == -1 && !compositeViewCfgExpandedByDefault(parentTdb,membersOfView->tags[ix],NULL)) || (firstOpened != -1 && firstOpened != ix)) printf(" style=\"display:none\""); printf("><TD width=10> </TD>"); int ix2=ix; while(0 < ix2--) printf("<TD width=100> </TD>"); printf("<TD colspan=%d>",membersOfView->count+1); - safef(varName, sizeof(varName), "%s", view->track); if(configurable[ix] != cfgNone) - { - cfgByCfgType(configurable[ix],db,cart,view->subtracks,varName, + { // Hint: subtrack is model but named for view + cfgByCfgType(configurable[ix],db,cart,view->subtracks,view->track, membersOfView->titles[ix],TRUE); #ifndef SUBTRACK_CFG - cfgLinkToDependentCfgs(cart,parentTdb,varName); + cfgLinkToDependentCfgs(cart,parentTdb,view->track); #endif///ndef SUBTRACK_CFG } } } } puts("</TABLE>"); freeMem(matchedViewTracks); return TRUE; } char *compositeLabelWithVocabLink(char *db,struct trackDb *parentTdb, struct trackDb *childTdb, char *vocabType, char *label) /* If the parentTdb has a controlledVocabulary setting and the vocabType is found, then label will be wrapped with the link to display it. Return string is cloned. */ {