e1988a798585c610e2399538a900fd57cfa83d63 galt Tue Apr 22 11:19:22 2025 -0700 Fixes VCF does not work on extended case-color options in Get DNA for vcf, vcfTabix, and vcfPhasedTrio. fixes #16386 diff --git src/hg/hgc/vcfClick.c src/hg/hgc/vcfClick.c index 06849667560..aafd9acbfd6 100644 --- src/hg/hgc/vcfClick.c +++ src/hg/hgc/vcfClick.c @@ -7,30 +7,31 @@ #include "dystring.h" #include "errCatch.h" #include "hCommon.h" #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" #include "trackHub.h" +#include "featureBits.h" #define NA "n/a" static void printKeysWithDescriptions(struct vcfFile *vcff, int wordCount, char **words, 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"). */ { int i; for (i = 0; i < wordCount; i++) { if (i > 0) printf(", "); char *displayKey = words[i]; @@ -509,95 +510,142 @@ boolean showLeftBase = (rec->chromStart == vcfStart+1); (void)vcfRecordTrimAllelesRight(rec); char *displayAls[rec->alleleCount]; makeDisplayAlleles(rec, showLeftBase, leftBase, 20, TRUE, FALSE, displayAls); printPosOnChrom(seqName, rec->chromStart, rec->chromEnd, NULL, FALSE, rec->name); printf("Reference allele: %s
\n", displayAls[0]); vcfAltAlleleDetails(rec, displayAls); vcfQualDetails(rec); vcfFilterDetails(rec); vcfInfoDetails(rec, tdb->track, recordCount); pgSnpCodingDetail(rec); makeDisplayAlleles(rec, showLeftBase, leftBase, 5, FALSE, TRUE, displayAls); vcfGenotypesDetails(rec, tdb, displayAls); } -void doVcfDetailsCore(struct trackDb *tdb, char *fileOrUrl, boolean isTabix) +void doVcfDetailsCore(struct trackDb *tdb, char *fileOrUrl, boolean isTabix, struct featureBits **pFbList, int rgnStart, int rgnEnd) /* Show item details using fileOrUrl. */ { +if (!pFbList) genericHeader(tdb, NULL); int start = cartInt(cart, "o"); int end = cartInt(cart, "t"); +if (pFbList) + { + start = rgnStart; + end = rgnEnd; + } + int vcfMaxErr = -1; struct vcfFile *vcff = NULL; /* protect against temporary network or parsing error */ struct errCatch *errCatch = errCatchNew(); if (errCatchStart(errCatch)) { if (isTabix) { char *indexUrl = trackDbSetting(tdb, "bigDataIndex"); vcff = vcfTabixFileAndIndexMayOpen(fileOrUrl, indexUrl, seqName, start, end, vcfMaxErr, -1); } else vcff = vcfFileMayOpen(fileOrUrl, seqName, start, end, vcfMaxErr, -1, TRUE); } errCatchEnd(errCatch); if (errCatch->gotError) { if (isNotEmpty(errCatch->message->string)) warn("%s", errCatch->message->string); } errCatchFree(&errCatch); + +struct featureBits *fbList = NULL, *fb; if (vcff != NULL) { struct vcfRecord *rec; // use the recordCount to make up unique id strings for html collapsible INFO section later int recordCount = 0; for (rec = vcff->records; rec != NULL; rec = rec->next) + { + if (pFbList) + { + AllocVar(fb); + fb->chrom = rec->chrom; + fb->start = rec->chromStart; + fb->end = rec->chromEnd; + fb->strand = '+'; + slAddHead(&fbList, fb); + } + else { if (rec->chromStart == start && rec->chromEnd == end) // in pgSnp mode, don't get name vcfRecordDetails(tdb, rec, recordCount); + } recordCount++; } } else + { + if (!pFbList) printf("Sorry, unable to open %s
\n", fileOrUrl); + } +if (pFbList) + { + slReverse(&fbList); + *pFbList = fbList; + } +else + { printTrackHtml(tdb); } +} -void doVcfTabixDetails(struct trackDb *tdb, char *item) +void doVcfTabixDetailsExt(struct trackDb *tdb, char *item, struct featureBits **pFbList, int start, int end) /* Show details of an alignment from a VCF file compressed and indexed by tabix. */ { knetUdcInstall(); if (udcCacheTimeout() < 300) udcSetCacheTimeout(300); struct sqlConnection *conn = NULL; + if (!trackHubDatabase(database)) conn = hAllocConnTrack(database, tdb); + char *fileOrUrl = bbiNameFromSettingOrTableChrom(tdb, conn, tdb->table, seqName); hFreeConn(&conn); -doVcfDetailsCore(tdb, fileOrUrl, TRUE); +doVcfDetailsCore(tdb, fileOrUrl, TRUE, pFbList, start, end); } +void doVcfTabixDetails(struct trackDb *tdb, char *item) +/* Show details of an alignment from a VCF file compressed and indexed by tabix. */ +{ +doVcfTabixDetailsExt(tdb, item, NULL, 0, 0); +} -void doVcfDetails(struct trackDb *tdb, char *item) + +void doVcfDetailsExt(struct trackDb *tdb, char *item, struct featureBits **pFbList, int start, int end) /* Show details of an alignment from an uncompressed VCF file. */ { struct customTrack *ct = lookupCt(tdb->track); struct sqlConnection *conn = NULL; char *table = tdb->table; if (ct) { conn = hAllocConn(CUSTOM_TRASH); table = ct->dbTableName; } else conn = hAllocConnTrack(database, tdb); char *fileOrUrl = bbiNameFromSettingOrTableChrom(tdb, conn, table, seqName); hFreeConn(&conn); -doVcfDetailsCore(tdb, fileOrUrl, FALSE); +doVcfDetailsCore(tdb, fileOrUrl, FALSE, pFbList, start, end); } + +void doVcfDetails(struct trackDb *tdb, char *item) +/* Show details of an alignment from an uncompressed VCF file. */ +{ +doVcfDetailsExt(tdb, item, NULL, 0, 0); +} +