bf1d058d73bdb153279eb4e530d1257d2ccc5675 angie Mon Jun 23 10:43:04 2014 -0700 Added ENCODE Regulatory summary tracks for clustered DNase and TFBS,with support for filtering based on BED5 score and factor/cellType/treatment. refs #11461 diff --git src/hg/hgVai/hgVai.c src/hg/hgVai/hgVai.c index da8ee5e..884a60a 100644 --- src/hg/hgVai/hgVai.c +++ src/hg/hgVai/hgVai.c @@ -70,30 +70,36 @@ " padding-top: 8px; padding-bottom: 5px; margin-top: 5px; margin-bottom: 5px }\n" ".sectionLiteHeader { font-weight: bold; font-size:larger; color:#000000;" " text-align:left; vertical-align:bottom; white-space:nowrap; }\n" "div.sectionLiteHeader.noReorderRemove { padding-bottom:5px; }\n" "div.sourceFilter { padding-top: 5px; padding-bottom: 5px }\n" "\n"); } INLINE void startCollapsibleSection(char *sectionSuffix, char *title, boolean onByDefault) // Wrap shared args to jsBeginCollapsibleSectionFontSize { jsBeginCollapsibleSectionFontSize(cart, "hgva", sectionSuffix, title, onByDefault, "1.1em"); } +INLINE void startSmallCollapsibleSection(char *sectionSuffix, char *title, boolean onByDefault) +// Wrap shared args to jsBeginCollapsibleSectionFontSize +{ +jsBeginCollapsibleSectionFontSize(cart, "hgva", sectionSuffix, title, onByDefault, "0.9em"); +} + #define endCollapsibleSection jsEndCollapsibleSection static struct dyString *onChangeStart() /* Start up a javascript onChange command */ { struct dyString *dy = jsOnChangeStart(); jsTextCarryOver(dy, hgvaRegionType); jsTextCarryOver(dy, hgvaRange); return dy; } static char *onChangeClade() /* Return javascript executed when they change clade. */ { @@ -240,30 +246,138 @@ printf("
\n", cgiScriptName(), cartUsualString(cart, "formMethod", "GET")); cartSaveSession(cart); //#*** ------------------ end verbatim --------------- printf("
" "Select Genome Assembly and Region
\n"); /* Print clade, genome and assembly line. */ hgGatewayCladeGenomeDb(); //#*** No longer ending form here... } +void factorSourceListInputProperties(struct trackDb *tdb, struct slName **retFactorList, + struct slName **retCellTypeList, struct slName **retTreatmentList) +/* Get a list of factor names used in factorSource track. */ +{ +char *inputsTable = trackDbSetting(tdb, "inputTrackTable"); +if (isEmpty(inputsTable)) + errAbort("track %s does not have an inputTrackTable setting", tdb->track); +char query[2048]; +struct sqlConnection *conn = hAllocConn(database); +if (retFactorList && retCellTypeList && retTreatmentList) + { + sqlSafef(query, sizeof(query), "select distinct(factor) from %s order by factor", inputsTable); + *retFactorList = sqlQuickList(conn, query); + sqlSafef(query, sizeof(query), "select distinct(cellType) from %s order by cellType", + inputsTable); + *retCellTypeList = sqlQuickList(conn, query); + sqlSafef(query, sizeof(query), "select distinct(treatment) from %s order by treatment", + inputsTable); + *retTreatmentList = sqlQuickList(conn, query); + } +else + errAbort("factorSourceListInputProperties: ret args must be non-NULL."); +hFreeConn(&conn); +} + +void printMultiselect(char *track, char *label, char *var, struct slName *optionList) +/* Print a label and multi-select, with hgva_track_var as cart var, with options in optionList, + * marking as selected any options stored in cart. */ +{ +printf("%s: ", label); +char cartVar[1024]; +safef(cartVar, sizeof(cartVar), "hgva_filter_%s_%s", track, var); +struct hash *selHash = NULL; +if (cartListVarExists(cart, cartVar)) + selHash = hashFromSlNameList(cartOptionalSlNameList(cart, cartVar)); +printf("\n"); +char shadowVar[1024]; +safef(shadowVar, sizeof(shadowVar), "%s%s", cgiMultListShadowPrefix(), cartVar); +cgiMakeHiddenVar(shadowVar, "1"); +//printf("\n", cartVar); +} + +void printFilterOptions(struct trackDb *tdb) +/* Print a collapsible filter section for tdb, with controls depending on tdb->type. */ +{ +char sectionName[512], cartVar[512]; +safef(sectionName, sizeof(sectionName), "%s_filter", tdb->track); +if (sameString(tdb->type, "factorSource")) + { + puts(""); + startSmallCollapsibleSection(sectionName, "filter items", FALSE); + struct slName *factorOptions = NULL, *cellTypeOptions = NULL, *treatmentOptions = NULL; + factorSourceListInputProperties(tdb, &factorOptions, &cellTypeOptions, + &treatmentOptions); + printMultiselect(tdb->track, "factor", "name", factorOptions); + printMultiselect(tdb->track, "cell type", "cellType", cellTypeOptions); + printMultiselect(tdb->track, "treatment", "treatment", treatmentOptions); + puts("
"); + puts("minimum peak score [0-1000]: "); + safef(cartVar, sizeof(cartVar), "hgva_filter_%s_score", tdb->track); + char *defaultScore = cartUsualString(cart, cartVar, "0"); + printf("
", + cartVar, defaultScore); + // The dimensions of ui-dropdownchecklist multiselects are not correct when + // the item is hidden. So, when this filter section is made visible, reinit them. + printf("\n", sectionName); + puts("
"); + endCollapsibleSection(); + } +if (startsWith("bed 5", tdb->type)) //#*** TODO: detect bed# properly + { + puts(""); + startSmallCollapsibleSection(sectionName, "filter items", FALSE); + //#*** Also watch out for noScoreFilter or whatever it's called + puts("minimum peak score [0-1000]: "); + safef(cartVar, sizeof(cartVar), "hgva_filter_%s_score", tdb->track); + char *defaultScore = cartUsualString(cart, cartVar, "0"); + printf("
", + cartVar, defaultScore); + puts("
"); + endCollapsibleSection(); + } +} + + typedef boolean TdbFilterFunction(struct trackDb *tdb, void *filterData); /* Return TRUE if tdb passes filter criteria. */ void rFilterTrackList(struct trackDb *trackList, struct slRef **pPassingRefs, TdbFilterFunction *filterFunc, void *filterData) /* Recursively apply filterFunc and filterData to all tracks in trackList and * their subtracks. Add an slRef to pPassingRefs for each track/subtrack that passes. * Caller should slReverse(pPassingRefs) when recursion is all done. */ { struct trackDb *tdb; for (tdb = trackList; tdb != NULL; tdb = tdb->next) { if (tdb->subtracks != NULL) rFilterTrackList(tdb->subtracks, pPassingRefs, filterFunc, filterData); if (filterFunc(tdb, filterData)) @@ -602,105 +716,143 @@ } void selectDbSnp(boolean gotSnp) /* Offer to include rsID (and other fields, or leave that for advanced output??) if available */ { if (!gotSnp) return; startCollapsibleSection("dbSnp", "Known variation", TRUE); cartMakeCheckBox(cart, "hgva_rsId", TRUE); printf("Include dbSNP " "rs# ID if one exists
\n"); puts("
"); endCollapsibleSection(); } +boolean isRegulatoryTrack(struct trackDb *tdb, void *filterData) +/* For now, just look for a couple specific tracks by tableName. */ +{ +//#*** NEED METADATA +return (sameString("wgEncodeRegDnaseClusteredV2", tdb->table) || + sameString("wgEncodeRegTfbsClusteredV3", tdb->table)); +} + +struct slRef *findRegulatoryTracks() +/* Look for the very limited set of Regulation tracks that hgVai offers. */ +{ +struct slRef *regTrackRefList = NULL; +tdbFilterGroupTrack(fullTrackList, fullGroupList, isRegulatoryTrack, + NULL, NULL, ®TrackRefList); +return regTrackRefList; +} + +void selectRegulatory(struct slRef *trackRefList) +/* If trackRefList is non-NULL, make a collapsible section with a checkbox for each track, + * labelled with longLabel, and optionally some filtering options. */ +{ +if (trackRefList != NULL) + { + startCollapsibleSection("Regulation", "Regulatory regions", FALSE); + // Use a table with checkboxes in one column and label/other stuff that depends on + // checkbox in other column. + puts(""); + struct slRef *ref; + for (ref = trackRefList; ref != NULL; ref = ref->next) + { + struct trackDb *tdb = ref->val; + char cartVar[512]; + safef(cartVar, sizeof(cartVar), "hgva_track_%s_%s", database, tdb->track); + puts(""); + } + puts("
"); + cartMakeCheckBox(cart, cartVar, FALSE); + puts(""); + struct trackDb *topTdb = trackDbTopLevelSelfOrParent(tdb); + printf("%s
\n", hgTrackUiName(), cartSidUrlString(cart), + topTdb->track, tdb->longLabel); + printFilterOptions(tdb); + puts("

"); + endCollapsibleSection(); + } +} + boolean isConsElTrack(struct trackDb *tdb, void *filterData) /* This is a TdbFilterFunction to get "phastConsNwayElements" tracks. */ { return (startsWith("phastCons", tdb->table) && stringIn("Elements", tdb->table)); } boolean isConsScoreTrack(struct trackDb *tdb, void *filterData) /* This is a TdbFilterFunction to get tracks that start with "phastCons" (no Elements) * or "phyloP". */ { return ((startsWith("phastCons", tdb->table) && !stringIn("Elements", tdb->table)) || startsWith("phyloP", tdb->table)); } void findCons(struct slRef **retElTrackRefList, struct slRef **retScoreTrackRefList) /* See if this database has Conserved Elements and/or Conservation Scores */ { tdbFilterGroupTrack(fullTrackList, fullGroupList, isConsElTrack, NULL, NULL, retElTrackRefList); tdbFilterGroupTrack(fullTrackList, fullGroupList, isConsScoreTrack, NULL, NULL, retScoreTrackRefList); } -void trackRefListToCheckboxes(struct slRef *trackRefList) +void trackCheckBoxSection(char *sectionSuffix, char *title, struct slRef *trackRefList) +/* If trackRefList is non-NULL, make a collapsible section with a checkbox for each track, + * labelled with longLabel. */ +{ +if (trackRefList != NULL) { + startCollapsibleSection(sectionSuffix, title, FALSE); struct slRef *ref; for (ref = trackRefList; ref != NULL; ref = ref->next) { struct trackDb *tdb = ref->val; char cartVar[512]; safef(cartVar, sizeof(cartVar), "hgva_track_%s_%s", database, tdb->track); cartMakeCheckBox(cart, cartVar, FALSE); struct trackDb *topTdb = trackDbTopLevelSelfOrParent(tdb); printf("%s
\n", hgTrackUiName(), cartSidUrlString(cart), topTdb->track, tdb->longLabel); } -} - -void selectCons(struct slRef *elTrackRefList, struct slRef *scoreTrackRefList) -/* Offer checkboxes for optional Conservation scores. */ -{ -if (elTrackRefList == NULL && scoreTrackRefList == NULL) - return; -if (elTrackRefList != NULL) - { - startCollapsibleSection("ConsEl", "Conserved elements", FALSE); - trackRefListToCheckboxes(elTrackRefList); puts("
"); endCollapsibleSection(); } -if (scoreTrackRefList != NULL) - { - startCollapsibleSection("ConsScore", "Conservation scores", - FALSE); - trackRefListToCheckboxes(scoreTrackRefList); - endCollapsibleSection(); - } } void selectAnnotations() /* Beyond predictions of protein-coding effect, what other basic data can we integrate? */ { struct slName *dbNsfpTables = findDbNsfpTables(); boolean gotSnp = findSnpBed4("", NULL, NULL); +struct slRef *regTrackRefList = findRegulatoryTracks(); struct slRef *elTrackRefList = NULL, *scoreTrackRefList = NULL; findCons(&elTrackRefList, &scoreTrackRefList); -if (dbNsfpTables == NULL && !gotSnp && elTrackRefList == NULL && scoreTrackRefList == NULL) +if (dbNsfpTables == NULL && !gotSnp && elTrackRefList == NULL && scoreTrackRefList == NULL + && regTrackRefList == NULL) return; puts("
"); printf("
Select More Annotations (optional)
\n"); // Make wrapper table for collapsible sections: puts(""); selectDbNsfp(dbNsfpTables); selectDbSnp(gotSnp); -selectCons(elTrackRefList, scoreTrackRefList); +selectRegulatory(regTrackRefList); +trackCheckBoxSection("ConsEl", "Conserved elements", elTrackRefList); +trackCheckBoxSection("ConsScore", "Conservation scores", scoreTrackRefList); puts("
"); } void selectFiltersFunc() /* Options to restrict variants based on gene region/soTerm from gpFx */ { startCollapsibleSection("filtersFunc", "Functional role", FALSE); printf("Include variants annotated as
\n"); cartMakeCheckBox(cart, "hgva_include_intergenic", TRUE); printf("intergenic
\n"); cartMakeCheckBox(cart, "hgva_include_upDownstream", TRUE); printf("upstream/downstream of gene
\n"); cartMakeCheckBox(cart, "hgva_include_nmdTranscript", TRUE); printf("in transcript already subject to nonsense-mediated decay (NMD)
\n"); cartMakeCheckBox(cart, "hgva_include_exonLoss", TRUE); @@ -849,62 +1001,65 @@ * If we get bold & offer 1000Genomes VCF, will def. need handling of split chroms. * Are we really going to offer genome-wide in hgVai? * Up-front limit on #rows of input ? * * Eventually, we might want a FormatVep that produces structs that are passed * forward to multiple output writers... I would want to send it lots of gratorData * like a formatter, but it would produce rows like an annoGrator. * Maybe annoGrators should accept a bunch of input rows like formatters? * or would this grator wrap all the input grators inside? */ void doMainPage() /* Print out initial HTML of control page. */ { jsInit(); -jsIncludeFile("jquery-ui.js", NULL); webIncludeResourceFile("jquery-ui.css"); -jsIncludeFile("hgVarAnnogrator.js", NULL); +webIncludeResourceFile("ui.dropdownchecklist.css"); boolean alreadyAgreed = cartUsualBoolean(cart, "hgva_agreedToDisclaimer", FALSE); printf("\n", alreadyAgreed ? "true" : "false"); addSomeCss(); printAssemblySection(); /* Check for variant custom tracks. If there are none, tell user they need to * upload at least one. */ struct slRef *varTrackList = NULL, *varGroupList = NULL; tdbFilterGroupTrack(fullTrackList, fullGroupList, isVariantCustomTrack, NULL, &varGroupList, &varTrackList); puts("
"); // Make wrapper table for collapsible sections: selectVariants(varGroupList, varTrackList); boolean gotGP = selectGenes(); if (gotGP) { selectAnnotations(); selectFilters(); selectOutput(); submitAndDisclaimer(); } printf("
"); jsReloadOnBackButton(cart); webNewSection("Using the Variant Annotation Integrator"); webIncludeHelpFile("hgVaiHelpText", FALSE); +jsIncludeFile("jquery-ui.js", NULL); +jsIncludeFile("hgVarAnnogrator.js", NULL); +jsIncludeFile("ui.dropdownchecklist.js", NULL); +jsIncludeFile("ddcl.js", NULL); } void doUi() /* Set up globals and make web page */ { cartWebStart(cart, database, "Variant Annotation Integrator"); doMainPage(); cartWebEnd(); /* Save variables. */ cartCheckout(&cart); } void checkVariantTrack(struct trackDb *tdb) /* variantTrack should be either pgSnp or VCF. */ { @@ -1014,153 +1169,262 @@ return tableName; } char *tagFromTableName(char *tableName, char *suffix) /* Generate a tag for VEP's extras column or VCF's info column. */ { char *p = strstr(tableName, "dbNsfp"); if (p != NULL) tableName = p + strlen("dbNsfp"); int suffixLen = (suffix == NULL) ? 0 : strlen(suffix); int tagSize = strlen(tableName) + suffixLen + 1; char *tag = cloneStringZ(tableName, tagSize); if (isNotEmpty(suffix)) safecat(tag, tagSize, suffix); touppers(tag); +// Some custom shortenings, to avoid very long tag names: +(void)strSwapStrs(tag, tagSize, "POLYPHEN", "PP"); +(void)strSwapStrs(tag, tagSize, "MUTATION", "MUT"); +(void)strSwapStrs(tag, tagSize, "PHYLOP", "PHP"); +(void)strSwapStrs(tag, tagSize, "PHASTCONS", "PHC"); +(void)strSwapStrs(tag, tagSize, "ELEMENTS", "EL"); +(void)strSwapStrs(tag, tagSize, "PRIMATES", "PRIM"); +(void)strSwapStrs(tag, tagSize, "PLACENTAL", "PLAC"); +if (regexMatch(tag, "^PH.*[0-9]WAY")) + (void)strSwapStrs(tag, tagSize, "WAY", "W"); +(void)strSwapStrs(tag, tagSize, "WGENCODEREGDNASECLUSTERED", "DNASE"); +(void)strSwapStrs(tag, tagSize, "WGENCODEREGTFBSCLUSTERED", "TFBS"); return tag; } enum PolyPhen2Subset stripSubsetFromTrackName(char *trackName) /* trackName may have a _suffix for a subset of PolyPhen2; convert that to enum * and zero out the suffix so we have the real trackName. */ { enum PolyPhen2Subset subset = noSubset; char *p = strchr(trackName, ':'); if (p != NULL) { if (sameString(p+1, "HDIV")) subset = HDIV; else if (sameString(p+1, "HVAR")) subset = HVAR; else errAbort("unrecognized suffix in track_suffix '%s'", trackName); *p = '\0'; } return subset; } void updateGratorListAndVepExtra(struct annoGrator *grator, struct annoGrator **pGratorList, struct annoFormatter *vepOut, enum PolyPhen2Subset subset, - char *column, char *description) + char *column, char *description, boolean isReg) /* If grator is non-NULL, add it to gratorList and vepOut's list of items for EXTRAs column. */ { if (grator == NULL) return; slAddHead(pGratorList, grator); if (vepOut != NULL) { char *tableName = tableNameFromSourceName(grator->streamer.name); char *suffix = NULL; if (subset == HDIV) suffix = "HDIV"; else if (subset == HVAR) suffix = "HVAR"; char *tag = tagFromTableName(tableName, suffix); if (isEmpty(description)) description = grator->streamer.name; + if (isReg) + annoFormatVepAddRegulatory(vepOut, (struct annoStreamer *)grator, tag, description, column); + else annoFormatVepAddExtraItem(vepOut, (struct annoStreamer *)grator, tag, description, column); } } INLINE void updateGratorList(struct annoGrator *grator, struct annoGrator **pGratorList) /* If grator is non-NULL, add it to gratorList. */ { -updateGratorListAndVepExtra(grator, pGratorList, NULL, 0, NULL, NULL); +updateGratorListAndVepExtra(grator, pGratorList, NULL, 0, NULL, NULL, FALSE); } void addDbNsfpSeqChange(char *trackName, struct annoAssembly *assembly, struct hash *gratorsByName, struct annoGrator **pGratorList) // If the user has selected dbNsfp* data, we also need the underlying dbNsfpSeqChange // data, so annoFormatVep can tell whether the variant and gpFx are consistent with the // variant and transcript that dbNsfp used to calculate scores. { //#*** Yet another place where we need metadata: char *seqChangeTable = "dbNsfpSeqChange"; if (hashFindVal(gratorsByName, seqChangeTable) == NULL) { char *fileName = fileNameFromTable(seqChangeTable); if (fileName == NULL) errAbort("'%s' requested, but I can't find fileName for %s", trackName, seqChangeTable); struct annoGrator *grator = gratorFromBigDataFileOrUrl(fileName, assembly, NO_MAXROWS, agoNoConstraint); updateGratorList(grator, pGratorList); hashAdd(gratorsByName, seqChangeTable, grator); } } +static struct dyString *dyInfo = NULL; + +struct hash *getTrackFilterVars(char *track) +/* Return a hash of filter variable names (cart variable suffixes) to slName lists of values. */ +{ +char filterPrefix[512]; +safef(filterPrefix, sizeof(filterPrefix), "hgva_filter_%s_", track); +struct slPair *filterVars = cartVarsWithPrefix(cart, filterPrefix), *var; +int prefixLen = strlen(filterPrefix); +struct hash *varHash = hashNew(0); +for (var = filterVars; var != NULL; var = var->next) + { + char *varName = var->name+prefixLen; + char *val = var->val; + struct hashEl *hel = hashLookup(varHash, varName); + if (hel != NULL) + slNameAddHead((struct slName **)(&hel->val), val); + else + hashAdd(varHash, varName, slNameNew(val)); + } +return varHash; +} + +INLINE boolean isNotAll(struct slName *valList) +/* Return TRUE unless valList has one element with name "All" (for multiselects). */ +{ +if (slCount(valList) == 1 && sameString(valList->name, "All")) + return FALSE; +return TRUE; +} + +void factorSourceGratorAddFilter(struct annoGrator *grator, char *name, struct slName *valList) +/* Add filter to factorSource grator. */ +//#*** Do these smarts belong here in hgVai? Probably not -- should be an hg/lib module with +//#*** UI/metadata smarts. +{ +struct annoStreamer *gStreamer = (struct annoStreamer *)grator; +struct annoFilter *filter = NULL; +if (sameString(name, "name") || sameString(name, "cellType") || sameString(name, "treatment")) + { + if (valList && isNotAll(valList)) + filter = annoFilterFromAsColumn(gStreamer->asObj, name, afMatch, valList); + } +else if (sameString(name, "score")) + filter = annoFilterFromAsColumn(gStreamer->asObj, name, afGTE, valList); +else + errAbort("Unrecognized filter name '%s' for %s, type=factorSource", name, gStreamer->name); +if (filter) + gStreamer->addFilters(gStreamer, filter); +} + +void bed5AddFilter(struct annoGrator *grator, char *name, struct slName *valList) +/* Add filter to bed 5 grator. */ +{ +struct annoStreamer *gStreamer = (struct annoStreamer *)grator; +struct annoFilter *filter = NULL; +if (sameString(name, "name")) + { + if (valList && isNotAll(valList)) + filter = annoFilterFromAsColumn(gStreamer->asObj, name, afMatch, valList); + } +else if (sameString(name, "score")) + filter = annoFilterFromAsColumn(gStreamer->asObj, name, afGTE, valList); +else + errAbort("Unrecognized filter name '%s' for %s, type=bed 5", name, gStreamer->name); +if (filter) + gStreamer->addFilters(gStreamer, filter); +} + +void addFiltersToGrator(struct annoGrator *grator, struct trackDb *tdb) +/* Look for filter variables in the cart and add filters to grator accordingly. */ +{ +struct hash *varHash = getTrackFilterVars(tdb->track); +struct hashEl *hel, *helList = hashElListHash(varHash); +for (hel = helList; hel != NULL; hel = hel->next) + { + char *filterName = hel->name; + struct slName *valList = hel->val; +//#*** Need a much better way to dispatch... + if (sameString("factorSource", tdb->type)) + factorSourceGratorAddFilter(grator, filterName, valList); + else if (startsWith("bed 5", tdb->type)) + bed5AddFilter(grator, filterName, valList); + else + dyStringPrintf(dyInfo, "Ignoring %s filter %s\n", tdb->track, filterName); + } +hashFree(&varHash); +} + void addOutputTracks(struct annoGrator **pGratorList, struct hash *gratorsByName, struct annoFormatter *vepOut, struct annoAssembly *assembly, char *chrom, boolean doHtml) // Construct grators for tracks selected to appear in EXTRAS column { char trackPrefix[128]; safef(trackPrefix, sizeof(trackPrefix), "hgva_track_%s_", database); int trackPrefixLen = strlen(trackPrefix); struct slPair *trackVar, *trackVars = cartVarsWithPrefix(cart, trackPrefix); for (trackVar = trackVars; trackVar != NULL; trackVar = trackVar->next) { char *val = trackVar->val; if (! (sameWord(val, "on") || atoi(val) > 0)) continue; char *trackName = trackVar->name + trackPrefixLen; if (sameString(trackName, "dbNsfpPolyPhen2")) // PolyPhen2 must have a suffix now -- skip obsolete cartVar from existing carts continue; struct annoGrator *grator = hashFindVal(gratorsByName, trackName); if (grator != NULL) // We already have this as a grator: continue; enum PolyPhen2Subset subset = noSubset; char *description = NULL; char *column = NULL; + boolean isReg = FALSE; if (startsWith("dbNsfp", trackName)) { // trackName for PolyPhen2 has a suffix for subset -- strip it if we find it: subset = stripSubsetFromTrackName(trackName); description = dbNsfpDescFromTableName(trackName, subset, doHtml); addDbNsfpSeqChange(trackName, assembly, gratorsByName, pGratorList); char *fileName = fileNameFromTable(trackName); if (fileName != NULL) grator = gratorFromBigDataFileOrUrl(fileName, assembly, NO_MAXROWS, agoNoConstraint); } else { struct trackDb *tdb = tdbForTrack(database, trackName, &fullTrackList); if (tdb != NULL) { grator = gratorFromTrackDb(assembly, tdb->table, tdb, chrom, NO_MAXROWS, NULL, agoNoConstraint); if (grator != NULL) + { //#*** Need something more sophisticated but this works for our //#*** limited selection of extra tracks: if (asColumnFind(grator->streamer.asObj, "name") != NULL) column = "name"; + addFiltersToGrator(grator, tdb); + } description = tdb->longLabel; + isReg = isRegulatoryTrack(tdb, NULL); } } - updateGratorListAndVepExtra(grator, pGratorList, vepOut, subset, column, description); + updateGratorListAndVepExtra(grator, pGratorList, vepOut, subset, column, description, isReg); if (grator != NULL) hashAdd(gratorsByName, trackName, grator); } } void addFilterTracks(struct annoGrator **pGratorList, struct hash *gratorsByName, struct annoAssembly *assembly, char *chrom) // Add grators for filters (not added to vepOut): { if (!cartUsualBoolean(cart, "hgva_include_snpCommon", TRUE)) { struct annoGrator *grator = gratorForSnpBed4(gratorsByName, "Common", assembly, chrom, agoMustNotOverlap, NULL); updateGratorList(grator, pGratorList); } @@ -1818,30 +2082,31 @@ if (varTdb == NULL) { if (isHubTrack(variantTrack)) warn("Can't find hub track '%s'", variantTrack); else warn("Can't find tdb for variant track '%s'", variantTrack); } else checkVariantTrack(varTdb); return varTdb; } void doQuery() /* Translate simple form inputs into anno* components and execute query. */ { +dyInfo = dyStringNew(0); char *chrom = NULL; uint start = 0, end = 0; if (sameString(regionType, hgvaRegionTypeRange)) getCartPosOrDie(&chrom, &start, &end); struct annoAssembly *assembly = getAnnoAssembly(database); char *geneTrack = cartString(cart, "hgva_geneTrack"); struct trackDb *geneTdb = tdbForTrack(database, geneTrack, &fullTrackList); if (geneTdb == NULL) { warn("Can't find tdb for gene track %s", geneTrack); doUi(); return; } @@ -1897,48 +2162,50 @@ struct annoGrator *gratorList = NULL; slAddHead(&gratorList, gpVarGrator); if (snpGrator != NULL) slAddHead(&gratorList, snpGrator); // Text or HTML output? char *outFormat = cartUsualString(cart, "hgva_outFormat", "vepTab"); boolean doHtml = sameString(outFormat, "vepHtml"); // Initialize VEP formatter: struct annoFormatter *vepOut = annoFormatVepNew("stdout", doHtml, primary, primaryLongLabel, (struct annoStreamer *)gpVarGrator, geneTdb->longLabel, (struct annoStreamer *)snpGrator, - snpDesc); + snpDesc, assembly); addOutputTracks(&gratorList, gratorsByName, vepOut, assembly, chrom, doHtml); addFilterTracks(&gratorList, gratorsByName, assembly, chrom); slReverse(&gratorList); if (doHtml) { webStart(cart, database, "Annotated Variants in VEP/HTML format"); } else { // Undo the htmlPushEarlyHandlers() because after this point they make ugly text: popWarnHandler(); popAbortHandler(); textOpen(); webStartText(); } +if (isNotEmpty(dyInfo->string)) + puts(dyInfo->string); struct annoGratorQuery *query = annoGratorQueryNew(assembly, primary, gratorList, vepOut); struct slName *comment; for (comment = commentList; comment != NULL; comment = comment->next) vepOut->comment(vepOut, comment->name); if (chrom != NULL) annoGratorQuerySetRegion(query, chrom, start, end); annoGratorQueryExecute(query); annoGratorQueryFree(&query); if (doHtml) webEnd(); else textOutClose(&compressPipeline); }