26a38dbb5ff226e6848067217518ff9e212696b8 kent Sat Jan 30 11:43:20 2021 -0800 Refactoring facetedTable stuff from a hgc module into a library routine. diff --git src/hg/hgc/facetedBar.c src/hg/hgc/facetedBar.c index 0d7a876..2cfc1ff 100644 --- src/hg/hgc/facetedBar.c +++ src/hg/hgc/facetedBar.c @@ -1,243 +1,63 @@ #include "common.h" #include "hash.h" #include "hdb.h" #include "web.h" #include "hvGfx.h" #include "trashDir.h" #include "hCommon.h" #include "hui.h" #include "asParse.h" #include "hgc.h" #include "trackHub.h" #include "hgColors.h" #include "fieldedTable.h" #include "tablesTables.h" #include "facetField.h" - #include "barChartBed.h" -#include "barChartData.h" -#include "barChartSample.h" -#include "barChartUi.h" #include "hgConfig.h" +#include "facetedTable.h" #include "facetedBar.h" -struct facetedTable -/* Help manage a faceted table */ - { - struct facetedTable *next; - char *name; /* Name of file or database table */ - char *varPrefix; /* Prefix used on variables */ - }; - -struct facetedTable *facetedTableNew(char *name, char *varPrefix) -{ -struct facetedTable *ft; -AllocVar(ft); -ft->name = cloneString(name); -ft->varPrefix = cloneString(varPrefix); -return ft; -} - -void facetedTableFree(struct facetedTable **pFt) -/* Free up resources associated with faceted table */ -{ -struct facetedTable *ft = *pFt; -if (ft != NULL) - { - freeMem(ft->name); - freeMem(ft->varPrefix); - freez(pFt); - } -} - - -void facetedTableWebInit() -/* Print out scripts and css that we need. We should be in a page body or title. */ -{ -webIncludeResourceFile("facets.css"); -printf("\t\t"); -printf("\t\t\n" - "\n" - "\t\t\n" - "\t\t\n" - "\n" - "\t\t\n" - "\t\t\n" - ); -printf(""); -} - -char *facetedTableSelOp(struct facetedTable *ft, struct cart *cart) -/* Look up selOp in cart */ -{ -char var[256]; -safef(var, sizeof(var), "%s_facet_op", ft->varPrefix); -return cartOptionalString(cart, var); -} - -char *facetedTableSelField(struct facetedTable *ft, struct cart *cart) -/* Look up sel field in cart */ -{ -char var[256]; -safef(var, sizeof(var), "%s_facet_fieldName", ft->varPrefix); -return cartOptionalString(cart, var); -} - -char *facetedTableSelVal(struct facetedTable *ft, struct cart *cart) -/* Look up sel val in cart */ -{ -char var[256]; -safef(var, sizeof(var), "%s_facet_fieldVal", ft->varPrefix); -return cartOptionalString(cart, var); -} - -char *facetedTableSelList(struct facetedTable *ft, struct cart *cart) -/* Look up sel val in cart */ -{ -char var[256]; -safef(var, sizeof(var), "%s_facet_selList", ft->varPrefix); -return cartOptionalString(cart, var); -} - -void facetedTableRemoveOpVars(struct facetedTable *ft, struct cart *cart) -/* Remove sel op/field/name vars from cart */ -{ -char var[256]; -safef(var, sizeof(var), "%s_facet_op", ft->varPrefix); -cartRemove(cart, var); -safef(var, sizeof(var), "%s_facet_fieldVal", ft->varPrefix); -cartRemove(cart, var); -safef(var, sizeof(var), "%s_facet_fieldName", ft->varPrefix); -cartRemove(cart, var); -} - -boolean facetedTableUpdateOnFacetClick(struct facetedTable *ft, struct cart *cart) -/* If we got called by a click on a facet deal with that and return TRUE, else do - * nothing and return false */ -{ -char *selOp = facetedTableSelOp(ft, cart); -if (selOp) - { - char *selFieldName = facetedTableSelField(ft, cart); - char *selFieldVal = facetedTableSelVal(ft, cart); - if (selFieldName && selFieldVal) - { - char selListVar[256]; - safef(selListVar, sizeof(selListVar), "%s_facet_selList", ft->varPrefix); - char *selectedFacetValues=cartUsualString(cart, selListVar, ""); - struct facetField *selList = deLinearizeFacetValString(selectedFacetValues); - selectedListFacetValUpdate(&selList, selFieldName, selFieldVal, selOp); - char *newSelectedFacetValues = linearizeFacetVals(selList); - cartSetString(cart, selListVar, newSelectedFacetValues); - facetedTableRemoveOpVars(ft, cart); - } - return TRUE; - } -else - return FALSE; -} - struct wrapContext /* Context used by various wrappers. */ { - int nameIx; /* First col by convention is name */ - int countIx; /* Index of count in row */ int colorIx; /* Index of color in row */ int valIx; /* Where value lives */ double maxVal;/* Maximum of any total value */ }; void wrapVal(struct fieldedTable *table, struct fieldedRow *row, char *field, char *val, char *shortVal, void *context) /* Write out wrapper draws a SVG bar*/ { struct wrapContext *wc = context; char *color = "#000000"; int colorIx = wc->colorIx; if (colorIx >= 0) color = row->row[colorIx]; double x = sqlDouble(val); int width = 500, height = 13; // These are units of ~2010 pixels or something double barWidth = (double)width*x/wc->maxVal; printf("", barWidth, height); printf("", barWidth, height, color); printf(""); printf(" %6.2f", x); } -double fieldedTableMaxInCol(struct fieldedTable *table, int colIx) -/* Figure out total and count columns from context and use them to figure - * out maximum mean value */ -{ -boolean firstTime = TRUE; -double max = 0.0; -struct fieldedRow *fr; -for (fr = table->rowList; fr != NULL; fr = fr->next) - { - double val = sqlDouble(fr->row[colIx]); - if (firstTime) - { - max = val; - firstTime = FALSE; - } - else if (max < val) - max = val; - } -return max; -} - -#ifdef OLD -double calcMaxMean(struct fieldedTable *table, struct wrapContext *context) -/* Go through text table figureing out mean for each row based on - * context fields. Return max of the means */ -{ -boolean firstTime = TRUE; -double max = 0.0; -struct fieldedRow *fr; -int countIx = context->countIx; -int totalIx = context->totalIx; -for (fr = table->rowList; fr != NULL; fr = fr->next) - { - double val = sqlDouble(fr->row[totalIx])/sqlDouble(fr->row[countIx]); - if (firstTime) - { - max = val; - firstTime = FALSE; - } - else if (max < val) - max = val; - } -return max; -} -#endif /* OLD */ - struct fieldedTable *addChartVals(struct fieldedTable *table, struct barChartBed *chart) /* All a new column with chart values */ { if (chart->expCount != table->rowCount) errAbort("Mismatch in field counts between %s (%d) and barChartBed (%d)", table->name, table->rowCount, chart->expCount); int oldFieldCount = table->fieldCount; int newFieldCount = oldFieldCount+1; char *newRow[newFieldCount]; int i; for (i=0; ifields[i]; newRow[oldFieldCount] = "val"; struct fieldedTable *newTable = fieldedTableNew(table->name, newRow, newFieldCount); struct fieldedRow *fr; @@ -249,80 +69,71 @@ char buf[16]; safef(buf, sizeof(buf), "%g", chart->expScores[rowIx]); newRow[oldFieldCount] = lmCloneString(newTable->lm, buf); fieldedTableAdd(newTable, newRow, newFieldCount, fr->id); } return newTable; } void facetedBarChart(char *item, struct barChartBed *chart, struct trackDb *tdb, double maxVal, char *statsFile, char *facets, char *metric) { char *trackName = tdb->track; struct sqlConnection *conn = sqlConnect(database); struct hash *emptyHash = hashNew(0); struct hash *wrapperHash = hashNew(0); -struct facetedTable *ft = facetedTableNew(tdb->shortLabel, trackName); -/* Write out html to pull in the other files we use. */ -facetedTableWebInit(); +/* Write out html to pull in the other files we use and make white background */ +hInsideStyleToWhite(); /* Set up url that has enough context to get back to us. */ struct dyString *returnUrl = dyStringNew(0); dyStringPrintf(returnUrl, "../cgi-bin/hgc?g=%s", trackName); if (item != NULL) dyStringPrintf(returnUrl, "&i=%s", item); dyStringPrintf(returnUrl, "&%s", cartSidUrlString(cart)); -/* Working within a form we save context */ +/* Working within a form we save context. It'd be nice to work outside of form someday. */ printf("
\n"); printf("
"); cartSaveSession(cart); cgiContinueHiddenVar("g"); cgiContinueHiddenVar("i"); -/* Put up the big faceted search table in a new div */ - /* Load up table from tsv file */ char *requiredStatsFields[] = {"count",}; struct fieldedTable *statsTable = fieldedTableFromTabFile(statsFile, statsFile, requiredStatsFields, ArraySize(requiredStatsFields)); struct fieldedTable *table = addChartVals(statsTable, chart); -/* Update facet selections from users input if any */ -facetedTableUpdateOnFacetClick(ft, cart); - -/* Do facet selection calculations */ -char *selList = facetedTableSelList(ft, cart); -struct facetField *ffArray[table->fieldCount]; -struct fieldedTable *selected = facetFieldsFromFieldedTable(table, selList, ffArray); +/* Update facet selections from users input if any and get selected part of table */ +struct facetedTable *facTab = facetedTableFromTable(table, trackName, facets); +facetedTableUpdateOnClick(facTab, cart); +struct fieldedTable *selected = facetedTableSelect(facTab, cart); - - -/* Set up wrappers for some of output fields */ -struct wrapContext context = {.nameIx = 0, - .countIx = fieldedTableFindFieldIx(table, "count"), +/* Set up context for functions that wrap output fields */ +struct wrapContext context = { .valIx = fieldedTableFindFieldIx(table, "val"), .colorIx = fieldedTableFindFieldIx(table, "color"), }; context.maxVal = fieldedTableMaxInCol(table, context.valIx); -/* Put up faceted search and table of visible fields. */ +/* Add wrapper function(s) */ +hashAdd(wrapperHash, "val", wrapVal); + +/* Pick which fields to display. We'll take the first field whatever it is + * named, and also count, and the "val" field we added and wrapped. */ char displayList[256]; safef(displayList, sizeof(displayList), "%s,count,val", table->fields[0]); -hashAdd(wrapperHash, "val", wrapVal); -webFilteredFieldedTable(cart, selected, - displayList, returnUrl->string, trackName, - 32, wrapperHash, &context, - FALSE, NULL, - selected->rowCount, 7, - NULL, emptyHash, - ffArray, facets, - NULL); + +facetedTableWriteHtml(facTab, cart, selected, displayList, + returnUrl->string, 32, wrapperHash, &context, 7); + /* Clean up and go home. */ printf("
\n"); hashFree(&emptyHash); +facetedTableFree(&facTab); sqlDisconnect(&conn); }