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);
+}
+