294e28961da0eab069c44113ff02dbd6008bb9cf angie Mon Oct 27 22:13:02 2014 -0700 I was under the mistaken impression that VCF header ##INFO andencouraged." This change remove errors about missing descriptions that were causing hgTables to give up after 101 errors on a track hub VCF. While inspecting the code I found that hgc's vcfClick.c printKeysWithDescriptions had never made use of its infoDefs arg as intended, so descriptions from ##ALT (symbolic alternate alleles) and ##FILTER were not displayed -- fixed that. refs #14231 diff --git src/hg/hgc/vcfClick.c src/hg/hgc/vcfClick.c index e366656..c1d23ac 100644 --- src/hg/hgc/vcfClick.c +++ src/hg/hgc/vcfClick.c @@ -10,105 +10,123 @@ #include "hdb.h" #include "hgc.h" #include "htmshell.h" #include "jsHelper.h" #include "pgSnp.h" #include "regexHelper.h" #include "trashDir.h" #include "knetUdc.h" #include "udc.h" #include "vcf.h" #include "vcfUi.h" #define NA "<em>n/a</em>" static void printKeysWithDescriptions(struct vcfFile *vcff, int wordCount, char **words, - struct vcfInfoDef *infoDefs) -/* Given an array of keys, print out a list of values with - * descriptions if descriptions are available. */ + struct vcfInfoDef *infoDefs, boolean stripToSymbol) +/* Given an array of keys, print out a list of values with descriptions if descriptions are + * available. If stripToSymbol, when searching infoDefs, pick the actual key out of + * <>'s and other extraneous stuff (e.g. "(C)<DEL>" --> "DEL"). */ { int i; for (i = 0; i < wordCount; i++) { if (i > 0) printf(", "); - char *key = words[i]; - const struct vcfInfoDef *def = vcfInfoDefForKey(vcff, key); - char *htmlKey = htmlEncode(key); - if (def != NULL) - printf("%s (%s)", htmlKey, def->description); + char *displayKey = words[i]; + char *descKey = displayKey; + if (stripToSymbol) + { + char *p = strchr(displayKey, '<'); + if (p) + { + descKey = cloneString(p+1); + p = strchr(descKey, '>'); + if (p) + *p = '\0'; + } + } + char *description = NULL; + struct vcfInfoDef *def; + for (def = infoDefs; def != NULL; def = def->next) + if (sameString(descKey, def->key)) + { + description = def->description; + break; + } + char *htmlKey = htmlEncode(displayKey); + if (description) + printf("%s (%s)", htmlKey, description); else printf("%s", htmlKey); } printf("<BR>\n"); } static void vcfAltAlleleDetails(struct vcfRecord *rec, char **displayAls) /* If VCF header specifies any symbolic alternate alleles, pull in descriptions. */ { printf("<B>Alternate allele(s):</B> "); if (rec->alleleCount < 2 || sameString(rec->alleles[1], ".")) { printf(NA"<BR>\n"); return; } struct vcfFile *vcff = rec->file; -printKeysWithDescriptions(vcff, rec->alleleCount-1, &(displayAls[1]), vcff->altDefs); +printKeysWithDescriptions(vcff, rec->alleleCount-1, &(displayAls[1]), vcff->altDefs, TRUE); } static void vcfQualDetails(struct vcfRecord *rec) /* If VCF header specifies a quality/confidence score (not "."), print it out. */ { printf("<B>Quality/confidence score:</B> %s<BR>\n", sameString(rec->qual, ".") ? NA : rec->qual); } static void vcfFilterDetails(struct vcfRecord *rec) /* If VCF header specifies any filters, pull in descriptions. */ { if (rec->filterCount == 0 || sameString(rec->filters[0], ".")) printf("<B>Filter:</B> "NA"<BR>\n"); else if (rec->filterCount == 1 && sameString(rec->filters[0], "PASS")) printf("<B>Filter:</B> PASS<BR>\n"); else { printf("<B>Filter failures:</B> "); printf("<font style='font-weight: bold; color: #FF0000;'>\n"); struct vcfFile *vcff = rec->file; - printKeysWithDescriptions(vcff, rec->filterCount, rec->filters, vcff->filterDefs); + printKeysWithDescriptions(vcff, rec->filterCount, rec->filters, vcff->filterDefs, FALSE); printf("</font>\n"); } } static void vcfInfoDetails(struct vcfRecord *rec) /* Expand info keys to descriptions, then print out keys and values. */ { if (rec->infoCount == 0) return; struct vcfFile *vcff = rec->file; puts("<B>INFO column annotations:</B><BR>"); puts("<TABLE border=0 cellspacing=0 cellpadding=2>"); int i; for (i = 0; i < rec->infoCount; i++) { struct vcfInfoElement *el = &(rec->infoElements[i]); const struct vcfInfoDef *def = vcfInfoDefForKey(vcff, el->key); - if (def == NULL) - continue; printf("<TR valign='top'><TD align=\"right\"><B>%s:</B></TD><TD style=width:15%%;'>", el->key); int j; - enum vcfInfoType type = def->type; + enum vcfInfoType type = def ? def->type : vcfInfoString; if (type == vcfInfoFlag && el->count == 0) printf("Yes"); // no values, so we can't call vcfPrintDatum... // However, if this is older VCF, type vcfInfoFlag might have a value. for (j = 0; j < el->count; j++) { if (j > 0) printf(", "); if (el->missingData[j]) printf("."); else vcfPrintDatum(stdout, el->values[j], type); } if (def != NULL) printf(" </TD><TD>%s", def->description); else