de29d745d32fb04a5187fb5998cc94bbb9bf41a4 angie Wed Aug 9 13:39:59 2017 -0700 Add optional HGVS output to annoGratorGpVar and hgVai. Since annoGratorGpVar is genePred-based, it can't yet take advantage of variantProjector's full PSL+CDS+sequence support, so when transcripts don't align cleanly to genome, HGVS c./n./p. output may be incorrect. refs #19968 diff --git src/hg/hgVai/hgVai.c src/hg/hgVai/hgVai.c index 24d4ac0..4784225 100644 --- src/hg/hgVai/hgVai.c +++ src/hg/hgVai/hgVai.c @@ -968,30 +968,58 @@ isVisible ? "block" : "none"); cartMakeCheckBox(cart, "hgva_txStatus_refSeqStatus", FALSE); puts("Include the " "<A HREF=" REFSEQ_STATUS_DOC_URL " " "TARGET=_BLANK>RefSeq status</A> of each transcript.<BR>"); puts("</div>"); } printf("<div class=\"noTxStatus\" style=\"display: %s;\">", somethingIsVisible ? "none" : "block"); puts("No transcript status data are available for the selected gene track."); puts("</div>"); puts("<BR>"); endCollapsibleSection(); } +static void selectHgvsOut() +/* Offer HGVS output choices */ +{ +startCollapsibleSection("hgvsOut", "HGVS variant nomenclature", TRUE); +printf("The <a href='http://www.hgvs.org/' target=_blank>Human Genome Variation Society (HGVS)</a> " + "has established a " + "<a href='http://varnomen.hgvs.org/' target=_blank>sequence variant nomenclature</a>, " + "an international standard used to report variation in " + "genomic, transcript and protein sequences.<br>\n"); +cartMakeCheckBox(cart, "hgva_hgvsG", FALSE); +printf("Include HGVS genomic (g.) terms in output<br>\n"); +cartMakeCheckBox(cart, "hgva_hgvsCN", FALSE); +printf("Include HGVS coding (c.) terms if applicable, otherwise noncoding (n.) terms, in output" + "<br>\n"); +cartMakeCheckBox(cart, "hgva_hgvsP", FALSE); +printf("Include HGVS protein (p.) terms (if applicable) in output<br>\n"); +cartMakeCheckBox(cart, "hgva_hgvsPAddParens", FALSE); +printf("When including HGVS protein (p.) terms, add parentheses around changes to emphasize " + "that they are predictions<br>\n"); +cartMakeCheckBox(cart, "hgva_hgvsBreakDelIns", FALSE); +printf("For variants that involve both a deletion and insertion, " + "including multi-nucleotide variants, " + "include the deleted sequence (e.g. show \"delAGinsTT\" instead of only \"delinsTT\")" + "<br>\n"); +puts("<br>"); +endCollapsibleSection(); +} + boolean isHg19RegulatoryTrack(struct trackDb *tdb, void *filterData) /* For now, just look for a couple specific tracks by tableName. */ { //#*** NEED METADATA return (sameString("wgEncodeRegDnaseClusteredV3", tdb->table) || sameString("wgEncodeRegTfbsClusteredV3", tdb->table)); } boolean isHg38RegulatoryTrack(struct trackDb *tdb, void *filterData) /* For now, just look for a couple specific tracks by tableName. */ { //#*** NEED METADATA return (sameString("wgEncodeRegDnaseClustered", tdb->table) || sameString("wgEncodeRegTfbsClusteredV3", tdb->table)); } @@ -1117,30 +1145,31 @@ struct slName *dbNsfpTables = findDbNsfpTables(); boolean gotSnp = findSnpBed4("", NULL, NULL); struct slRef *elTrackRefList = NULL, *scoreTrackRefList = NULL; findCons(&elTrackRefList, &scoreTrackRefList); struct slRef *cosmicTrackRefList = findTrackRefByName("cosmic"); boolean hasTxStat = hasTxStatus(); if (dbNsfpTables == NULL && !gotSnp && elTrackRefList == NULL && scoreTrackRefList == NULL && cosmicTrackRefList == NULL && !hasTxStat) return; puts("<BR>"); printf("<div class='sectionLiteHeader'>Select More Annotations (optional)</div>\n"); // Make wrapper table for collapsible sections: puts("<TABLE border=0 cellspacing=5 cellpadding=0 style='padding-left: 10px;'>"); selectDbNsfp(dbNsfpTables); selectTxStatus(hasTxStat, geneTrack); +selectHgvsOut(); selectDbSnp(gotSnp); trackCheckBoxSection("Cosmic", "COSMIC", cosmicTrackRefList); trackCheckBoxSection("ConsEl", "Conserved elements", elTrackRefList); trackCheckBoxSection("ConsScore", "Conservation scores", scoreTrackRefList); puts("</TABLE>"); } void selectFiltersFunc() /* Options to restrict variants based on gene region/soTerm from gpFx */ { startCollapsibleSection("filtersFunc", "Functional role", FALSE); printf("Include variants annotated as<BR>\n"); jsMakeSetClearContainer(); cartMakeCheckBox(cart, "hgva_include_intergenic", TRUE); printf("intergenic<BR>\n"); @@ -1398,30 +1427,47 @@ ZeroVar(&aggvFuncFilter); aggvFuncFilter.intergenic = cartUsualBoolean(cart, "hgva_include_intergenic", TRUE); aggvFuncFilter.upDownstream = cartUsualBoolean(cart, "hgva_include_upDownstream", TRUE); aggvFuncFilter.nmdTranscript = cartUsualBoolean(cart, "hgva_include_nmdTranscript", TRUE); aggvFuncFilter.exonLoss = cartUsualBoolean(cart, "hgva_include_exonLoss", TRUE); aggvFuncFilter.utr = cartUsualBoolean(cart, "hgva_include_utr", TRUE); aggvFuncFilter.cdsSyn = cartUsualBoolean(cart, "hgva_include_cdsSyn", TRUE); aggvFuncFilter.cdsNonSyn = cartUsualBoolean(cart, "hgva_include_cdsNonSyn", TRUE); aggvFuncFilter.intron = cartUsualBoolean(cart, "hgva_include_intron", TRUE); aggvFuncFilter.splice = cartUsualBoolean(cart, "hgva_include_splice", TRUE); aggvFuncFilter.nonCodingExon = cartUsualBoolean(cart, "hgva_include_nonCodingExon", TRUE); aggvFuncFilter.noVariation = cartUsualBoolean(cart, "hgva_include_noVariation", TRUE); annoGratorGpVarSetFuncFilter(gpVarGrator, &aggvFuncFilter); } +static void setHgvsOutOptions(struct annoGrator *gpVarGrator) +/* Use cart variables to configure gpVarGrator's HGVS output. */ +{ +uint hgvsOutOptions = 0; +if (cartUsualBoolean(cart, "hgva_hgvsG", FALSE)) + hgvsOutOptions |= HGVS_OUT_G; +if (cartUsualBoolean(cart, "hgva_hgvsCN", FALSE)) + hgvsOutOptions |= HGVS_OUT_CN; +if (cartUsualBoolean(cart, "hgva_hgvsP", FALSE)) + hgvsOutOptions |= HGVS_OUT_P; +if (cartUsualBoolean(cart, "hgva_hgvsPAddParens", FALSE)) + hgvsOutOptions |= HGVS_OUT_P_ADD_PARENS; +if (cartUsualBoolean(cart, "hgva_hgvsBreakDelIns", FALSE)) + hgvsOutOptions |= HGVS_OUT_BREAK_DELINS; +annoGratorGpVarSetHgvsOutOptions(gpVarGrator, hgvsOutOptions); +} + struct annoGrator *gratorForSnpBed4(struct hash *gratorsByName, char *suffix, struct annoAssembly *assembly, char *chrom, enum annoGratorOverlap overlapRule, char **retDescription) /* Look up snpNNNsuffix; if we find it, return a grator (possibly for a bigBed 4 file), * otherwise return NULL. */ { char *fileName = NULL; struct trackDb *tdb = NULL; if (! findSnpBed4(suffix, &fileName, &tdb)) return NULL; struct annoGrator *grator = NULL; // First look in gratorsByName to see if this grator has already been constructed: if (tdb != NULL) { @@ -2738,30 +2784,31 @@ if (! isCommandLine) doUi(); return; } primary = hAnnoStreamerFromTrackDb(assembly, varTdb->table, varTdb, chrom, maxVarRows, NULL); primaryLongLabel = varTdb->longLabel; } enum annoGratorOverlap geneOverlapRule = agoMustOverlap; struct joinerDtf *txStatusExtras = getTxStatusExtras(database, geneTrack); struct jsonElement *gpConfig = configForStreamer(database, geneTdb, txStatusExtras); struct annoGrator *gpVarGrator = hAnnoGratorFromTrackDb(assembly, geneTdb->table, geneTdb, chrom, ANNO_NO_LIMIT, primary->asObj, geneOverlapRule, gpConfig); setGpVarFuncFilter(gpVarGrator); +setHgvsOutOptions(gpVarGrator); // Some grators may be used as both filters and output values. To avoid making // multiple grators for the same source, hash them by trackName: struct hash *gratorsByName = hashNew(8); struct annoGrator *snpGrator = NULL; char *snpDesc = NULL; if (cartUsualBoolean(cart, "hgva_rsId", TRUE)) snpGrator = gratorForSnpBed4(gratorsByName, "", assembly, chrom, agoNoConstraint, &snpDesc); // Now construct gratorList in the order in which annoFormatVep wants to see them, // i.e. first the gpVar, then the snpNNN, then whatever else: struct annoGrator *gratorList = NULL; slAddHead(&gratorList, gpVarGrator); if (snpGrator != NULL)