4cab7f311cadce7428c1d7e1c4dfdcb0d3a43033 angie Wed Jul 27 10:32:19 2011 -0700 Feature #3710 (vcfTabix UI options): Added controls for selection of centervariant for haplotype clustering/sorting. Also, some hgc improvements: made the Genotype Details table into a collapsible section; better display of QUAL and FILTER column values, which also involved improving the representation of those columns in src/inc/vcf.h. diff --git src/hg/lib/vcfUi.c src/hg/lib/vcfUi.c new file mode 100644 index 0000000..a4927cd --- /dev/null +++ src/hg/lib/vcfUi.c @@ -0,0 +1,182 @@ +/* vcfUi - Variant Call Format user interface controls that are shared + * between more than one CGI. */ + +#include "common.h" +#include "cheapcgi.h" +#include "errCatch.h" +#include "hCommon.h" +#include "hui.h" +#include "vcf.h" +#include "vcfUi.h" +#if (defined USE_TABIX && defined KNETFILE_HOOKS) +#include "knetUdc.h" +#include "udc.h" +#endif//def USE_TABIX && KNETFILE_HOOKS + +INLINE char *nameOrDefault(char *thisName, char *defaultVal) +/* If thisName is not a placeholder value, return it; otherwise return default. */ +{ +if (isNotEmpty(thisName) && !sameString(thisName, ".")) + return thisName; +return defaultVal; +} + +#define VCF_HAPLOSORT_DEFAULT_DESC "middle variant in viewing window" + +static void vcfCfgHaplotypeCenterHiddens(char *track, char *ctrName, char *ctrChrom, int ctrPos) +/* Make hidden form inputs and button for setting the center variant for haplotype + * clustering/sorting in hgTracks. */ +{ +char cartVar[1024]; +safef(cartVar, sizeof(cartVar), "%s.centerVariantChrom", track); +cgiMakeHiddenVar(cartVar, ctrChrom); +safef(cartVar, sizeof(cartVar), "%s.centerVariantPos", track); +char ctrPosStr[16]; +safef(ctrPosStr, sizeof(ctrPosStr), "%d", ctrPos); +cgiMakeHiddenVar(cartVar, ctrPosStr); +safef(cartVar, sizeof(cartVar), "%s.centerVariantName", track); +cgiMakeHiddenVar(cartVar, ctrName); +} + +void vcfCfgHaplotypeCenter(struct cart *cart, struct trackDb *tdb, struct vcfFile *vcff, + char *thisName, char *thisChrom, int thisPos, char *formName) +/* If vcff has genotype data, show status and controls for choosing the center variant + * for haplotype clustering/sorting in hgTracks. */ +{ +if (vcff != NULL && vcff->genotypeCount > 1) + { +// cluster haplotypes or just show allele summary? +// if clustering haplotypes: +// track height? +// thicken lines? +// outline center variant? +// choose center variant? [hgc option to make this variant's coords the center of viewed region?] +// color haplotypes by red/blue or allele bases? + printf("<TABLE cellpadding=0><TR><TD>" + "<B>Haplotype sorting:</B> using "); + char cartVar[1024]; + safef(cartVar, sizeof(cartVar), "%s.centerVariantChrom", tdb->track); + char *centerChrom = cartOptionalString(cart, cartVar); + if (isEmpty(centerChrom)) + { + // Unspecified in cart -- describe the default action + printf(VCF_HAPLOSORT_DEFAULT_DESC " as anchor.</TD></TR>\n"); + if (isNotEmpty(thisChrom)) + { + // but we do have a candidate, so offer to make it the center: + puts("<TR><TD>"); + vcfCfgHaplotypeCenterHiddens(tdb->track, thisName, thisChrom, thisPos); + char label[256]; + safef(label, sizeof(label), "Use %s", nameOrDefault(thisName, "this variant")); + cgiMakeButton("submit", label); + printf(" as anchor</TD></TR>\n"); + } + else + printf("<TR><TD>To anchor the sorting to a particular variant, " + "click on the variant in the genome browser, " + "and then click on the 'Use this variant' button on the next page." + "</TD></TR>\n"); + } + else + { + // Describe the one specified in cart. + cgiMakeHiddenVar(cartVar, ""); + safef(cartVar, sizeof(cartVar), "%s.centerVariantPos", tdb->track); + int centerPos = cartInt(cart, cartVar); + safef(cartVar, sizeof(cartVar), "%s.centerVariantName", tdb->track); + char *centerName = cartString(cart, cartVar); + if (isNotEmpty(thisChrom)) + { + // These form inputs are for either "use me" or clear: + vcfCfgHaplotypeCenterHiddens(tdb->track, thisName, thisChrom, thisPos); + // Is this variant the same as the center variant specified in cart? + if (sameString(thisChrom, centerChrom) && sameString(thisName, centerName) && + thisPos == centerPos) + printf("this variant as anchor.</TD></TR>\n"); + else + { + // make a "use me" button + printf("%s at %s:%d as anchor.</TD></TR>\n<TR><TD>\n", + nameOrDefault(centerName, "variant"), centerChrom, centerPos+1); + char label[256]; + safef(label, sizeof(label), "Use %s", nameOrDefault(thisName, "this variant")); + cgiMakeButton("submit", label); + printf(" as anchor</TD></TR>\n"); + } + } + else + { + // Form inputs (in case the clear button is clicked) + vcfCfgHaplotypeCenterHiddens(tdb->track, centerName, centerChrom, centerPos); + printf("%s at %s:%d as anchor.</TD></TR>\n", + nameOrDefault(centerName, "variant"), centerChrom, centerPos+1); + } + // Make a clear button that modifies the hiddens using onClick + puts("<TR><TD>"); + struct dyString *onClick = dyStringNew(0); + dyStringPrintf(onClick, "updateOrMakeNamedVariable(%s, '%s.centerVariantChrom', ''); ", + formName, tdb->track); + dyStringPrintf(onClick, "updateOrMakeNamedVariable(%s, '%s.centerVariantName', ''); ", + formName, tdb->track); + dyStringPrintf(onClick, "updateOrMakeNamedVariable(%s, '%s.centerVariantPos', 0);", + formName, tdb->track); + dyStringPrintf(onClick, "document.%s.submit(); return false;", formName); + cgiMakeButtonWithOnClick("submit", "Clear selection", NULL, onClick->string); + printf(" (use " VCF_HAPLOSORT_DEFAULT_DESC ")</TD></TR>\n"); + } + puts("</TABLE>"); + } +} + +//TODO: share this code w/hgTracks, hgc in hg/lib/vcfFile.c +static struct vcfFile *vcfHopefullyOpenHeader(struct cart *cart, struct trackDb *tdb) +/* Defend against network errors and return the vcfFile object with header data, or NULL. */ +{ +#if (defined USE_TABIX && defined KNETFILE_HOOKS) +knetUdcInstall(); +if (udcCacheTimeout() < 300) + udcSetCacheTimeout(300); +#endif//def USE_TABIX && KNETFILE_HOOKS +char *db = cartString(cart, "db"); +struct sqlConnection *conn = hAllocConnTrack(db, tdb); +char *fileOrUrl = bbiNameFromSettingOrTable(tdb, conn, tdb->table); +hFreeConn(&conn); +int vcfMaxErr = 100; +struct vcfFile *vcff = NULL; +/* protect against temporary network error */ +struct errCatch *errCatch = errCatchNew(); +if (errCatchStart(errCatch)) + { + vcff = vcfTabixFileMayOpen(fileOrUrl, NULL, 0, 0, vcfMaxErr); + } +errCatchEnd(errCatch); +if (errCatch->gotError) + { + if (isNotEmpty(errCatch->message->string)) + warn("unable to open %s: %s", fileOrUrl, errCatch->message->string); + } +errCatchFree(&errCatch); +return vcff; +} + +void vcfCfgUi(struct cart *cart, struct trackDb *tdb, char *name, char *title, boolean boxed) +/* VCF: Variant Call Format. redmine #3710 */ +{ +boxed = cfgBeginBoxAndTitle(tdb, boxed, title); +printf("<TABLE%s><TR><TD>", boxed ? " width='100%'" : ""); +struct vcfFile *vcff = vcfHopefullyOpenHeader(cart, tdb); +vcfCfgHaplotypeCenter(cart, tdb, vcff, NULL, NULL, 0, "mainForm"); +// filter: +// by qual column +// by filter column +// color bases like pgSnp or some better palette? + + +printf("</TD></TR></TABLE>"); + +if (!boxed && fileExists(hHelpFile("hgVcfTrackHelp"))) + printf("<P><A HREF=\"../goldenPath/help/hgVcfTrackHelp.html\" TARGET=_BLANK>VCF " + "configuration help</A></P>"); +cfgEndBox(boxed); +} +