7537f40b289d8ff6b05f41f66e683d97a130b794 kate Tue Nov 17 12:24:52 2020 -0800 Rough cut adding category file setting to barChart. refs #22075 diff --git src/hg/lib/barChartUi.c src/hg/lib/barChartUi.c index 255b10b..3855f22 100644 --- src/hg/lib/barChartUi.c +++ src/hg/lib/barChartUi.c @@ -1,22 +1,23 @@ /* Bar chart track controls */ /* Copyright (C) 2015 The Regents of the University of California * See README in this or parent directory for licensing information. */ #include "cheapcgi.h" #include "cart.h" +#include "net.h" #include "hui.h" #include "trackDb.h" #include "jsHelper.h" #include "hCommon.h" #include "rainbow.h" #include "htmlColor.h" #include "barChartCategory.h" #include "barChartUi.h" /* Restrict features on right-click (popup) version */ static boolean isPopup = FALSE; /* Convenience functions for category filter controls */ @@ -144,93 +145,169 @@ { char cartVar[1024]; char buf[512]; safef(cartVar, sizeof(cartVar), "%s.%s", track, BAR_CHART_LOG_TRANSFORM); boolean isLogTransform = cartCgiUsualBoolean(cart, cartVar, BAR_CHART_LOG_TRANSFORM_DEFAULT); safef(buf, sizeof buf, "%sViewLimitsMaxLabel %s", track, isLogTransform ? "disabled" : ""); printf("View limits maximum:\n", buf); safef(cartVar, sizeof(cartVar), "%s.%s", track, BAR_CHART_MAX_VIEW_LIMIT); int viewMax = cartCgiUsualInt(cart, cartVar, BAR_CHART_MAX_VIEW_LIMIT_DEFAULT); cgiMakeIntVarWithExtra(cartVar, viewMax, 4, isLogTransform ? "disabled" : ""); char *unit = trackDbSettingClosestToHomeOrDefault(tdb, BAR_CHART_UNIT, ""); printf(" %s (range 0-%d)\n", buf, unit, round(barChartUiMaxMedianScore(tdb))); } +// TODO: libify +static boolean isUrl(char *url) +{ +return ((startsWith("http://", url) + || startsWith("https://", url) + || startsWith("ftp://", url))); +} + struct barChartCategory *barChartUiGetCategories(char *database, struct trackDb *tdb) -/* Get category colors and descriptions. Use barChartColors setting if present. - If not, if there is a barChartBars setting, assign rainbow colors. - * O/w look for a table naed track+Category, and use labels and colors there +/* Get category colors and descriptions. + Use labels in tab-sep file specified by barChartCategoryUrl setting, o/w in barChartBars setting. + If colors are not specified via barChartColors setting or second column in category file, + assign rainbow colors. */ { -struct barChartCategory *categs = NULL; +int count = 0; +struct slName *labels = NULL, *colors = NULL; +char *fileOrUrl = trackDbSetting(tdb, BAR_CHART_CATEGORY_URL); +if (isEmpty(fileOrUrl)) + { + // use trackDb settings for labels and perhaps colors + char *labelSetting = trackDbSetting(tdb, BAR_CHART_CATEGORY_LABELS); + if (isEmpty(labelSetting)) + { + errAbort("barChart track %s missing required setting: %s or %s\n", + tdb->track, BAR_CHART_CATEGORY_LABELS, BAR_CHART_CATEGORY_URL); + } char *words[BAR_CHART_MAX_CATEGORIES]; -char *colorWords[BAR_CHART_MAX_CATEGORIES]; -char *labels = trackDbSettingClosestToHome(tdb, BAR_CHART_CATEGORY_LABELS); -char *colors = trackDbSettingClosestToHome(tdb, BAR_CHART_CATEGORY_COLORS); -struct barChartCategory *categ = NULL; + count = chopLine(cloneString(labelSetting), words); + labels = slNameListFromStringArray(words, count); + char *colorSetting = trackDbSetting(tdb, BAR_CHART_CATEGORY_COLORS); + if (isNotEmpty(colorSetting)) + { + int ct = chopLine(cloneString(colorSetting), words); + if (ct != count) + errAbort("barChart track %s settings mismatch: %s (%d) and %s (%d)\n", + tdb->track, BAR_CHART_CATEGORY_LABELS, count, BAR_CHART_CATEGORY_COLORS, ct); + colors = slNameListFromStringArray(words, count); + } + } +else + { + // use file for labels and perhaps colors + struct lineFile *lf = NULL; + +#ifdef TODO +// TODO: protect against network error +struct errCatch *errCatch = errCatchNew(); +if (errCatchStart(errCatch)) + { + if (isUrl(fileOrUrl)) + { + lf = netLineFileOpen(fileOrUrl); + else + lf = lineFileMayOpen(fileOrUrl, TRUE); + } + } +errCatchEnd(errCatch); +if (errCatch->gotError) + { + if (isNotEmpty(errCatch->message->string)) + warn("unable to open %s: %s", fileOrUrl, errCatch->message->string); + } +errCatchFree(&errCatch); +#endif -if (labels == NULL) + if (isUrl(fileOrUrl)) + lf = netLineFileOpen(fileOrUrl); + else + lf = lineFileMayOpen(fileOrUrl, TRUE); + char *line = NULL; + int cols = 0; + while (lineFileNextReal(lf, &line)) + { + char *words[2]; + int wordCount = chopTabs(line, words); + if (cols) { - errAbort("barChart track %s missing required %s setting\n", tdb->track, BAR_CHART_CATEGORY_LABELS); + if (wordCount != cols) + errAbort("barChart track %s category file %s expecting %d words, got %d", + tdb->track, fileOrUrl, cols, wordCount); } else { - int count = chopLine(cloneString(labels), words); - struct rgbColor *rainbow = getRainbow(&saturatedRainbowAtPos, count); - if (colors != NULL) + cols = wordCount; + } + slAddHead(&labels, slNameNew(words[0])); + if (wordCount == 2) + slAddHead(&colors, slNameNew(words[1])); + count++; + } + slReverse(&labels); + slReverse(&colors); + } + +// populate categories +struct barChartCategory *categs = NULL, *categ = NULL; +struct rgbColor *rainbow = NULL; +if (!colors) { - int colorCount = chopLine(cloneString(colors), colorWords); - if (colorCount != count) - warn("barChart track %s mismatch between label (%d) and color (%d) settings", - tdb->track, count, colorCount); + rainbow = getRainbow(&saturatedRainbowAtPos, count); } int i; char buf[6]; - for (i=0; iid = i; safef(buf, sizeof buf, "%d", i); categ->name = cloneString(buf); - categ->label = words[i]; + categ->label = labels->name; if (colors) { unsigned rgb; - char *color = colorWords[i]; + char *color = colors->name; if (htmlColorForCode(color, &rgb)) { categ->color = rgb; } else if (htmlColorForName(color, &rgb)) { categ->color = rgb; } else warn("barChart track %s unknown color %s. Must be one of %s\n", tdb->track, color, slNameListToString(htmlColorNames(),',')); } else { categ->color = ((rainbow[i].r & 0xff)<<16) + ((rainbow[i].g & 0xff)<<8) + ((rainbow[i].b & 0xff)); } slAddHead(&categs, categ); + labels = labels->next; + if (colors) + colors = colors->next; } slReverse(&categs); - } return categs; } struct barChartCategory *barChartUiGetCategoryById(int id, char *database, struct trackDb *tdb) /* Get category info by id */ { struct barChartCategory *categ; struct barChartCategory *categs = barChartUiGetCategories(database, tdb); for (categ = categs; categ != NULL; categ = categ->next) if (categ->id == id) return categ; return NULL; }