42d91822ec103cfcc74e9f69b39d3ad8d886c278 angie Wed Mar 18 15:25:15 2020 -0700 Add a new trackDb setting hapClusterMethod and corresponding UI option for drawing haplotypes in VCF file order instead of clustering. refs #25197 Applied the new setting to mm10 strainSNPs and increased its default height so that strain labels appear in the left label area. diff --git src/hg/lib/vcfUi.c src/hg/lib/vcfUi.c index 8b6c592..d4c94e6 100644 --- src/hg/lib/vcfUi.c +++ src/hg/lib/vcfUi.c @@ -36,100 +36,123 @@ 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, char *track, boolean parentLevel, 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) { - printf("<TABLE cellpadding=0><TR><TD>" - "<B>Haplotype sorting order:</B> using "); + printf("using "); char *centerChrom = cartOptionalStringClosestToHome(cart, tdb, parentLevel, "centerVariantChrom"); 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>"); + puts("<TR><TD></TD><TD>"); vcfCfgHaplotypeCenterHiddens(track, thisName, thisChrom, thisPos); char label[256]; safef(label, sizeof(label), "Use %s", nameOrDefault(thisName, "this variant")); cgiMakeButton("setCenterSubmit", label); printf(" as anchor</TD></TR>\n"); } else - printf("<TR><TD>To anchor the sorting to a particular variant, " + printf("<TR><TD></TD><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. int centerPos = cartUsualIntClosestToHome(cart, tdb, parentLevel, "centerVariantPos", -1); char *centerName = cartStringClosestToHome(cart, tdb, parentLevel, "centerVariantName"); if (isNotEmpty(thisChrom)) { // These form inputs are for either "use me" or clear: vcfCfgHaplotypeCenterHiddens(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", + printf("%s at %s:%d as anchor.</TD></TR>\n<TR><TD></TD><TD>\n", nameOrDefault(centerName, "variant"), centerChrom, centerPos+1); char label[256]; safef(label, sizeof(label), "Use %s", nameOrDefault(thisName, "this variant")); cgiMakeButton("replaceCenterSubmit", label); printf(" as anchor</TD></TR>\n"); } } else { // Form inputs (in case the clear button is clicked) vcfCfgHaplotypeCenterHiddens(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>"); + puts("<TR><TD></TD><TD>"); struct dyString *onClick = dyStringNew(0); dyStringPrintf(onClick, "updateOrMakeNamedVariable(%s, '%s.centerVariantChrom', ''); ", formName, track); dyStringPrintf(onClick, "updateOrMakeNamedVariable(%s, '%s.centerVariantName', ''); ", formName, track); dyStringPrintf(onClick, "updateOrMakeNamedVariable(%s, '%s.centerVariantPos', 0);", formName, track); dyStringPrintf(onClick, "document.%s.submit(); return false;", formName); cgiMakeButtonWithOnClick("clearCenterSubmit", "Clear selection", NULL, onClick->string); printf(" (use " VCF_HAPLOSORT_DEFAULT_DESC ")</TD></TR>\n"); } - puts("</TABLE>"); + } +} + +static void vcfCfgHaplotypeMethod(struct cart *cart, struct trackDb *tdb, char *track, + boolean parentLevel, struct vcfFile *vcff) +/* If vcff has genotype data, offer the option of whether to cluster or just use the order + * of genotypes in the VCF file. For clustering, show status and controls for choosing the + * center variant for haplotype clustering/sorting in hgTracks. */ +{ +if (vcff != NULL && vcff->genotypeCount > 1) + { + printf("<TABLE cellpadding=0><TR><TD colspan=2>" + "<B>Haplotype sorting order:</B></TD></TR><TR><TD>\n"); + char *hapMethod = cartOrTdbString(cart, tdb, VCF_HAP_METHOD_VAR, VCF_DEFAULT_HAP_METHOD); + char varName[1024]; + safef(varName, sizeof(varName), "%s." VCF_HAP_METHOD_VAR, track); + cgiMakeRadioButton(varName, VCF_HAP_METHOD_CENTER_WEIGHTED, + sameString(hapMethod, VCF_HAP_METHOD_CENTER_WEIGHTED)); + printf("</TD><TD>"); + vcfCfgHaplotypeCenter(cart, tdb, track, parentLevel, vcff, NULL, NULL, 0, "mainForm"); + puts("<TR><TD>"); + cgiMakeRadioButton(varName, VCF_HAP_METHOD_FILE_ORDER, + sameString(hapMethod, VCF_HAP_METHOD_FILE_ORDER)); + puts("</TD><TD>Using the order in which samples appear in the underlying VCF file"); + puts("</TR></TD></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. */ { knetUdcInstall(); if (udcCacheTimeout() < 300) udcSetCacheTimeout(300); char *fileOrUrl = trackDbSetting(tdb, "bigDataUrl"); if (isEmpty(fileOrUrl)) { char *db = cartString(cart, "db"); char *table = tdb->table; @@ -224,31 +247,31 @@ printf("<B>Haplotype sorting display height:</B> \n"); int cartHeight = cartOrTdbInt(cart, tdb, VCF_HAP_HEIGHT_VAR, VCF_DEFAULT_HAP_HEIGHT); char varName[1024]; safef(varName, sizeof(varName), "%s." VCF_HAP_HEIGHT_VAR, name); cgiMakeIntVarInRange(varName, cartHeight, "Height (in pixels) of track", 5, "4", "2500"); puts("<BR>"); } } static void vcfCfgHapCluster(struct cart *cart, struct trackDb *tdb, struct vcfFile *vcff, char *name, boolean parentLevel) /* Show controls for haplotype-sorting display, which only makes sense to do when * the VCF file describes multiple genotypes. */ { vcfCfgHapClusterEnable(cart, tdb, name, parentLevel); -vcfCfgHaplotypeCenter(cart, tdb, name, parentLevel, vcff, NULL, NULL, 0, "mainForm"); +vcfCfgHaplotypeMethod(cart, tdb, name, parentLevel, vcff); vcfCfgHapClusterColor(cart, tdb, name, parentLevel); vcfCfgHapClusterTreeAngle(cart, tdb, name, parentLevel); vcfCfgHapClusterHeight(cart, tdb, vcff, name, parentLevel); } static void vcfCfgMinQual(struct cart *cart, struct trackDb *tdb, struct vcfFile *vcff, char *name, boolean parentLevel) /* If checkbox is checked, apply minimum value filter to QUAL column. */ { char cartVar[1024]; safef(cartVar, sizeof(cartVar), "%s." VCF_APPLY_MIN_QUAL_VAR, name); boolean applyFilter = cartOrTdbBoolean(cart, tdb, VCF_APPLY_MIN_QUAL_VAR, VCF_DEFAULT_APPLY_MIN_QUAL); cgiMakeCheckBox(cartVar, applyFilter); printf("<B>Exclude variants with Quality/confidence score (QUAL) score less than</B>\n");