9174a163b341bfd2dd5c8fe84952265e74bef32a angie Sun Sep 27 23:50:14 2020 -0700 Added setting sampleColorFile so one or more sample coloring schemes can be offered for the tree in VCF+tree tracks. refs #26177 TODO: document the new setting diff --git src/hg/lib/vcfUi.c src/hg/lib/vcfUi.c index 83066d9..53600c9 100644 --- src/hg/lib/vcfUi.c +++ src/hg/lib/vcfUi.c @@ -170,31 +170,36 @@ printf("using the tree specified in file associated with track"); } printf(""); cgiMakeRadioButton(varName, VCF_HAP_METHOD_CENTER_WEIGHTED, sameString(hapMethod, VCF_HAP_METHOD_CENTER_WEIGHTED)); printf(""); vcfCfgHaplotypeCenter(cart, tdb, track, parentLevel, vcff, NULL, NULL, 0, "mainForm"); puts(""); cgiMakeRadioButton(varName, VCF_HAP_METHOD_FILE_ORDER, sameString(hapMethod, VCF_HAP_METHOD_FILE_ORDER)); puts("using the order in which samples appear in the underlying VCF file"); puts(""); jsInlineF("$('input[type=radio][name=\"%s\"]').change(function() { " "if (this.value == '"VCF_HAP_METHOD_CENTER_WEIGHTED"') {" " $('#leafShapeContainer').show();" + " $('#sampleColorContainer').hide();" + "} else if (this.value == '"VCF_HAP_METHOD_TREE_FILE"') {" + " $('#sampleColorContainer').show();" + " $('#leafShapeContainer').hide();" "} else {" + " $('#sampleColorContainer').hide();" " $('#leafShapeContainer').hide();" "}});\n", varName); } } //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)) @@ -266,30 +271,71 @@ { cgiMakeRadioButton(varName, VCF_HAP_COLORBY_FUNCTION, sameString(colorBy, VCF_HAP_COLORBY_FUNCTION)); printf("reference alleles invisible, alternate alleles in " "red for non-synonymous, " "green for synonymous, " "blue for UTR/noncoding, " "black otherwise
\n"); } cgiMakeRadioButton(varName, VCF_HAP_COLORBY_REFALT, sameString(colorBy, VCF_HAP_COLORBY_REFALT)); printf("reference alleles in blue, alternate alleles in red
\n"); cgiMakeRadioButton(varName, VCF_HAP_COLORBY_BASE, sameString(colorBy, VCF_HAP_COLORBY_BASE)); printf("first base of allele (A = red, C = blue, G = green, T = magenta)
\n"); } +static void vcfCfgHapClusterSampleColor(struct cart *cart, struct trackDb *tdb, char *name, + boolean parentLevel) +/* If sampleColorFile specifies multiple files, when hapClusterMethod treeFile is selected, + * let the user choose sample-coloring scheme for the tree. */ +{ +char *tdbSetting = trackDbSetting(tdb, VCF_SAMPLE_COLOR_FILE); +if (tdbSetting && strchr(tdbSetting, ' ')) + { + char *hapMethod = cartOrTdbString(cart, tdb, VCF_HAP_METHOD_VAR, VCF_DEFAULT_HAP_METHOD); + printf("
\n", + startsWithWord(VCF_HAP_METHOD_TREE_FILE, hapMethod) ? "" : " style='display: none;'"); + printf("Sample coloring scheme for tree:
\n"); + char *setting = cartOrTdbString(cart, tdb, VCF_SAMPLE_COLOR_FILE, tdbSetting); + char *options[16]; + int optionCount = chopLine(tdbSetting, options); + char *labels[optionCount]; + char *values[optionCount]; + int i; + for (i = 0; i < optionCount; i++) + { + char *eq = strchr(options[i], '='); + if (eq) + { + *eq = '\0'; + labels[i] = options[i]; + replaceChar(options[i], '_', ' '); + values[i] = eq+1; + } + else + { + labels[i] = values[i] = options[i]; + } + } + char *selected = strchr(setting, ' ') ? values[0] : setting; + char varName[1024]; + safef(varName, sizeof varName, "%s." VCF_SAMPLE_COLOR_FILE, name); + cgiMakeDropListWithVals(varName, labels, values, optionCount, selected); + puts("
"); + } +} + static void vcfCfgHapClusterTreeAngle(struct cart *cart, struct trackDb *tdb, char *name, boolean parentLevel) /* Let the user choose branch shape. */ { // This option applies only to center-weighted clustering; don't show option when some other // method is selected. char *hapMethod = cartOrTdbString(cart, tdb, VCF_HAP_METHOD_VAR, VCF_DEFAULT_HAP_METHOD); printf("
\n", differentString(hapMethod, VCF_HAP_METHOD_CENTER_WEIGHTED) ? " style='display: none;'" : ""); printf("%s clustering tree leaf shape:
\n", vcfHaplotypeOrSample(cart)); char *treeAngle = cartOrTdbString(cart, tdb, VCF_HAP_TREEANGLE_VAR, VCF_DEFAULT_HAP_TREEANGLE); char varName[1024]; safef(varName, sizeof(varName), "%s." VCF_HAP_TREEANGLE_VAR, name); cgiMakeRadioButton(varName, VCF_HAP_TREEANGLE_TRIANGLE, sameString(treeAngle, VCF_HAP_TREEANGLE_TRIANGLE)); @@ -313,30 +359,31 @@ cgiMakeIntVarInRange(varName, cartHeight, "Height (in pixels) of track", 5, "4", "10000"); puts("
"); } } 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. */ { char *hapOrSample = vcfHaplotypeOrSample(cart); printf("

%s sorting display

\n", hapOrSample); vcfCfgHapClusterEnable(cart, tdb, name, parentLevel); vcfCfgHaplotypeMethod(cart, tdb, name, parentLevel, vcff); vcfCfgHapClusterTreeAngle(cart, tdb, name, parentLevel); +vcfCfgHapClusterSampleColor(cart, tdb, name, parentLevel); vcfCfgHapClusterColor(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("Exclude variants with Quality/confidence score (QUAL) score less than\n"); double minQual = cartOrTdbDouble(cart, tdb, VCF_MIN_QUAL_VAR, VCF_DEFAULT_MIN_QUAL);