21bf4f713e944af4e8810544d68c441510ea85a3 kate Wed Jul 26 16:31:01 2017 -0700 Add support for maxHeightPixels in trackDb and UI of barChart type tracks. refs #19872 diff --git src/hg/lib/barChartUi.c src/hg/lib/barChartUi.c index b5cfcbe..3903721 100644 --- src/hg/lib/barChartUi.c +++ src/hg/lib/barChartUi.c @@ -1,292 +1,307 @@ /* 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 "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 */ char *makeCategoryLabel(struct barChartCategory *categ) /* Display category color and label */ { char buf[256]; safef(buf, sizeof(buf), "" " %s", 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) { #define TABLE_COLUMNS 1 if (title != NULL) printf("%s\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=1; for (i=0; i=count) { printf(""); row++; col = 0; } j = row + col*(count/tableColumns+1); if (!isPopup) { printf("" "%s\n", name, categArray[j]->name, categArray[j]->checked ? "checked" : "", categArray[j]->label); } col++; } if ((i % tableColumns) != 0) while ((i++ % tableColumns) != 0) printf(""); printf("\n"); } static void makeCategoryCheckboxes(char *name, struct barChartCategory *categs, struct slName *checked) { puts("\n"); struct hash *checkHash = hashNew(0); struct slName *sel; for (sel = checked; sel != NULL; sel = sel->next) hashAdd(checkHash, sel->name, sel->name); puts(""); 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("
"); char buf[512]; safef(buf, sizeof(buf), "%s%s", cgiMultListShadowPrefix(), name); cgiMakeHiddenVar(buf, "0"); } /* Convenience functions for hgTrackUi */ double barChartUiMaxMedianScore(struct trackDb *tdb) /* Max median score, for scaling */ { char *setting = trackDbSettingClosestToHome(tdb, BAR_CHART_MAX_LIMIT); if (setting != NULL) { double max = sqlDouble(setting); if (max > 0.0) return max; } return BAR_CHART_MAX_LIMIT_DEFAULT; } void barChartUiViewTransform(struct cart *cart, char *track, struct trackDb *tdb) /* Checkboxes to select log-transform or autoscale RPKM values, or text input for view limits */ { char buf[512]; char cartVar[1024]; puts("Log10(x+1) transform:\n"); safef(cartVar, sizeof(cartVar), "%s.%s", track, BAR_CHART_LOG_TRANSFORM); boolean isLogTransform = cartCgiUsualBoolean(cart, cartVar, BAR_CHART_LOG_TRANSFORM_DEFAULT); cgiMakeCheckBoxWithId(cartVar, isLogTransform, cartVar); jsOnEventByIdF("change", cartVar, "barChartTransformChanged(event);"); puts("  "); puts("Autoscale:\n"); safef(cartVar, sizeof(cartVar), "%s.%s", track, BAR_CHART_AUTOSCALE); boolean isAutoScale = cartCgiUsualBoolean(cart, cartVar, BAR_CHART_AUTOSCALE_DEFAULT); cgiMakeCheckBoxWithId(cartVar, isAutoScale, cartVar); jsOnEventByIdF("change", cartVar, "barChartTransformChanged(event);"); boolean isViewLimits = !isAutoScale && !isLogTransform; safef(buf, sizeof buf, "%sViewLimitsMaxLabel %s", track, !isViewLimits ? "disabled" : ""); puts("  "); 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, !isViewLimits ? "disabled" : ""); char *unit = trackDbSettingClosestToHomeOrDefault(tdb, BAR_CHART_UNIT, ""); printf(" %s (range 0-%d)\n", buf, unit, round(barChartUiMaxMedianScore(tdb))); } +void barChartUiMaxHeight(struct cart *cart, char *track, struct trackDb *tdb) +/* Input to change maximum track height */ +{ +int min = BAR_CHART_MAX_HEIGHT_MIN; +int deflt = BAR_CHART_MAX_HEIGHT_DEFAULT; +int max = BAR_CHART_MAX_HEIGHT_MAX; +int settingsDefault; +wigFetchMinMaxPlusPixelsWithCart(cart, tdb, track, &min, &max, &deflt, &settingsDefault); +puts("Track height maximum:\n"); +char cartVar[1024]; +safef(cartVar, sizeof(cartVar), "%s.%s", track, HEIGHTPER); +cgiMakeIntVarWithLimits(cartVar, deflt, "Track height maximum", 0, min, max); +printf("pixels (range: %d to %d, default: %d)", min, max, settingsDefault); +} + 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 */ { struct barChartCategory *categs = NULL; 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; if (labels == NULL) { errAbort("barChart track %s missing required %s setting\n", tdb->track, BAR_CHART_CATEGORY_LABELS); } else { int count = chopLine(cloneString(labels), words); struct rgbColor *rainbow = getRainbow(&saturatedRainbowAtPos, count); if (colors != NULL) { 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); } int i; char buf[6]; for (i=0; iid = i; safef(buf, sizeof buf, "%d", i); categ->name = cloneString(buf); categ->label = words[i]; if (colors) { unsigned rgb; char *color = colorWords[i]; 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); } 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; } char *barChartUiGetCategoryLabelById(int id, char *database, struct trackDb *tdb) /* Get label for a category id */ { struct barChartCategory *categ = barChartUiGetCategoryById(id, database, tdb); if (categ == NULL) return "Unknown"; return categ->label; } 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); if (startsWith("big", tdb->type)) labelCfgUi(database, cart, tdb); -printf("\n\n
", - isPopup ? 75 : 100, boxed ?" width='100%'":""); - -char cartVar[1024]; /* Data transform (log, autoscale or viewlimits) */ -puts("
"); +char cartVar[1024]; +puts("

"); barChartUiViewTransform(cart, track, tdb); -puts("

"); +puts("

"); + +/* Maximum track height */ +puts("

"); +barChartUiMaxHeight(cart, track, tdb); +puts("

"); /* Category filter */ printf("
"); char *categoryLabel = trackDbSettingClosestToHomeOrDefault(tdb, BAR_CHART_CATEGORY_LABEL, BAR_CHART_CATEGORY_LABEL_DEFAULT); char *db = cartString(cart, "db"); struct barChartCategory *categs = barChartUiGetCategories(db, tdb); printf("
%s:\n", categoryLabel); safef(cartVar, sizeof(cartVar), "%s.%s", track, BAR_CHART_CATEGORY_SELECT); if (isPopup) { printf("", hTrackUiForTrack(track), track); } else { jsMakeCheckboxGroupSetClearButton(cartVar, TRUE); puts(" "); jsMakeCheckboxGroupSetClearButton(cartVar, FALSE); } printf("
"); 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
\n"); cfgEndBox(boxed); }