dea095643fe501ea9923781556921916ceff4d3e kate Thu Jan 26 14:19:23 2017 -0800 Initial cut of hgTracks and hgTrackUi for new barchart type track (generalization of GTEx gene expression display). refs #18736 diff --git src/hg/lib/barChartUi.c src/hg/lib/barChartUi.c new file mode 100644 index 0000000..a2ca0e9 --- /dev/null +++ src/hg/lib/barChartUi.c @@ -0,0 +1,213 @@ +/* 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 "hui.h" +#include "trackDb.h" +#include "jsHelper.h" +#include "hCommon.h" +#include "barChartCategory.h" +#include "barChartUi.h" + +/* Restrict features on right-click (popup) version */ +static boolean isPopup = FALSE; + +/* Convenience functions for category filter controls */ + + +static char *makeCategoryLabel(struct barChartCategory *categ) +{ +/* Display category color and label */ +char buf[256]; +safef(buf, sizeof(buf), "<td class='bcColorPatch' bgcolor=%X></td>" + "<td> %s</td>", + categ->color, categ->label); +return(cloneString(buf)); +} + +struct categorySelect + { + struct categorySelect *next; + char *name; + char *label; + boolean checked; + }; + +static void makeGroupCheckboxes(char *name, char *title, struct categorySelect *selects) +{ +if (title != NULL) + printf("<tr><td colspan=10><i><b>%s</b></i></td></tr><tr>\n", title); +int count = slCount(selects); +struct categorySelect **categArray; +AllocArray(categArray, count); +int i=0; +struct categorySelect *sel; +for (i=0, sel = selects; sel != NULL; sel = sel->next, i++) + categArray[i] = sel; +int col=0; +int row=0; +int tableColumns=3; +for (i=0; i<count; i++) + { + int j = row + col*(count/tableColumns+1); + if (j>=count) + { + printf("</tr><tr>"); + row++; + col = 0; + } + j = row + col*(count/tableColumns+1); + if (!isPopup) + { + printf("<td><input type=checkbox name=\"%s\" value=\"%s\" %s></td>" "<td>%s</td>\n", + name, categArray[j]->name, categArray[j]->checked ? "checked" : "", categArray[j]->label); + } + col++; + } +if ((i % tableColumns) != 0) + while ((i++ % tableColumns) != 0) + printf("<td></td>"); +printf("</tr><tr><td></td></tr>\n"); +} + +static void makeCategoryCheckboxes(char *name, struct barChartCategory *categs, + struct slName *checked) +{ +// TODO: use style sheet! +puts("<style>\n"); +puts(".bcColorPatch { padding: 0 10px; }\n"); +puts("</style>\n"); + +struct hash *checkHash = hashNew(0); +struct slName *sel; +for (sel = checked; sel != NULL; sel = sel->next) + hashAdd(checkHash, sel->name, sel->name); +puts("<table borderwidth=0 cellspacing=4><tr>"); +struct categorySelect *catSel; +struct barChartCategory *categ; +struct categorySelect *all = NULL; +for (categ = categs; categ != NULL; categ = categ->next) + { + AllocVar(catSel); + catSel->name = categ->name; + catSel->label = makeCategoryLabel(categ); + if (hashNumEntries(checkHash) == 0) + catSel->checked = TRUE; + else + catSel->checked = (hashLookup(checkHash, categ->name) != NULL); + slAddHead(&all, catSel); + } +slReverse(&all); +makeGroupCheckboxes(name, NULL, all); +puts("</tr></table>"); +char buf[512]; +safef(buf, sizeof(buf), "%s%s", cgiMultListShadowPrefix(), name); +cgiMakeHiddenVar(buf, "0"); +} + +/* Convenience functions for hgTrackUi */ + +void barChartUiLogTransform(struct cart *cart, char *track, struct trackDb *tdb) +/* Checkbox to select log-transformed RPKM values */ +{ +char cartVar[1024]; +char buf[512]; +puts("<b>Log10 transform:</b>\n"); +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, "onchange='barChartTransformChanged(\"%s\")'", track); +cgiMakeCheckBoxJS(cartVar, isLogTransform, buf); +} + +double barChartUiMaxMedianScore() +/* Max median score, for scaling */ +{ +//TODO: get from trackDb +return 10000; +} + +void barChartUiViewLimits(struct cart *cart, char *track, struct trackDb *tdb) +/* Set viewing limits if log transform not checked */ +{ +char cartVar[1024]; +char buf[512]; +boolean isLogTransform = cartCgiUsualBoolean(cart, cartVar, BAR_CHART_LOG_TRANSFORM_DEFAULT); +safef(buf, sizeof buf, "%sViewLimitsMaxLabel %s", track, isLogTransform ? "disabled" : ""); +printf("<span class='%s'><b>View limits maximum:</b></span>\n", buf); +safef(cartVar, sizeof(cartVar), "%s.%s", track, BAR_CHART_MAX_LIMIT); +int viewMax = cartCgiUsualInt(cart, cartVar, BAR_CHART_MAX_LIMIT_DEFAULT); +cgiMakeIntVarWithExtra(cartVar, viewMax, 4, isLogTransform ? "disabled" : ""); +printf("<span class='%s'> (range 0-%d)</span>\n", buf, round(barChartUiMaxMedianScore())); +} + +void barChartCfgUi(char *database, struct cart *cart, struct trackDb *tdb, char *track, + char *title, boolean boxed) +/* Bar chart track type */ +{ +if (cartVarExists(cart, "ajax")) + isPopup = TRUE; + +boxed = cfgBeginBoxAndTitle(tdb, boxed, title); +printf("\n<table id=barChartControls style='font-size:%d%%' %s>\n<tr><td>", + isPopup ? 75 : 100, boxed ?" width='100%'":""); + +char cartVar[1024]; + +/* Data transform. When selected, the next control (view limits max) is disabled */ + +puts("<div>"); +barChartUiLogTransform(cart, track, tdb); + +/* Viewing limits max. This control is disabled if log transform is selected */ +// construct class so JS can toggle +puts(" "); +barChartUiViewLimits(cart, track, tdb); +puts("</div>"); + +/* Color scheme */ +#ifdef COLOR_SCHEME +printf("<p><b>Category colors:</b>\n"); +safef(cartVar, sizeof(cartVar), "%s.%s", track, BAR_CHART_COLORS); +selected = cartCgiUsualString(cart, cartVar, BAR_CHART_COLORS_DEFAULT); +boolean isUserColors = sameString(selected, BAR_CHART_COLORS_USER); +cgiMakeRadioButton(cartVar, BAR_CHART_COLORS_USER, isUserColors); +printf("Defined\n"); +cgiMakeRadioButton(cartVar, BAR_CHART_COLORS_RAINBOW, !isUserColors); +printf("Rainbow\n"); +printf("</p>"); +#endif + +/* Category filter */ +printf("<br>"); +// TODO: +#define BAR_CHART_CATEGORY_LABEL "categoryLabel" +#define BAR_CHART_CATEGORY_LABEL_DEFAULT "Categories" +char *categoryLabel = trackDbSettingClosestToHomeOrDefault(tdb, + BAR_CHART_CATEGORY_LABEL, BAR_CHART_CATEGORY_LABEL_DEFAULT); +printf("<div><b>%s:</b>\n", categoryLabel); +safef(cartVar, sizeof(cartVar), "%s.%s", track, BAR_CHART_CATEGORY_SELECT); +if (isPopup) + { + printf("<a href='%s?g=%s'><button type='button'>Change</button><a>", + hTrackUiForTrack(track), track); + } +else + { + jsMakeCheckboxGroupSetClearButton(cartVar, TRUE); + puts(" "); + jsMakeCheckboxGroupSetClearButton(cartVar, FALSE); + } +printf("</div>"); +char *db = cartString(cart, "db"); +struct barChartCategory *categs = barChartGetCategories(db, track); +struct slName *selectedValues = NULL; +if (cartListVarExistsAnyLevel(cart, tdb, FALSE, BAR_CHART_CATEGORY_SELECT)) + selectedValues = cartOptionalSlNameListClosestToHome(cart, tdb, FALSE, BAR_CHART_CATEGORY_SELECT); +makeCategoryCheckboxes(cartVar, categs, selectedValues); + +puts("\n</table>\n"); +cfgEndBox(boxed); +}