a79fba9b734cc2dc74f8fe6365fe833f7a14c06b kent Mon Feb 1 17:27:55 2021 -0800 Adjusting to use the new interface to facetedTable, which now resides in a library module. No need to review. This module is about to get moved to oneShot. diff --git src/hg/hgFacetedBars/hgFacetedBars.c src/hg/hgFacetedBars/hgFacetedBars.c index 3876b1f..32dc173 100644 --- src/hg/hgFacetedBars/hgFacetedBars.c +++ src/hg/hgFacetedBars/hgFacetedBars.c @@ -3,292 +3,141 @@ #include "common.h" #include "linefile.h" #include "hash.h" #include "options.h" #include "jksql.h" #include "htmshell.h" #include "web.h" #include "cheapcgi.h" #include "cart.h" #include "hui.h" #include "udc.h" #include "knetUdc.h" #include "genbank.h" #include "tablesTables.h" #include "facetField.h" +#include "facetedTable.h" #include "sqlNum.h" /* Global Variables */ struct cart *cart; /* CGI and other variables */ struct hash *oldVars = NULL; char *database = NULL; char *genome = NULL; -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" - ); -} - -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 meanIx; /* The field that has total read count */ int colorIx; /* Index of color in row */ double maxMean;/* Maximum of any total value */ }; void wrapMean(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 mean = sqlDouble(val); int width = 500, height = 13; // These are units of ~2010 pixels or something double barWidth = (double)width*mean/wc->maxMean; printf("", barWidth, height); printf("", barWidth, height, color); printf(""); printf(" %6.2f", mean); } -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 */ void doBody() { /* Fake up a 'track' for development */ char *trackName = "cellFacetsJk1"; +/* Load up table from tsv file */ +char *statsFileName = "/gbdb/hg38/bbi/singleCellMerged/barChart.stats"; +char *requiredStatsFields[] = {"count","organ","cell_class","stage","cell_type"}; +struct fieldedTable *table = fieldedTableFromTabFile(statsFileName, statsFileName, + requiredStatsFields, ArraySize(requiredStatsFields)); +char *keyField = table->fields[0]; + struct sqlConnection *conn = sqlConnect(database); struct hash *emptyHash = hashNew(0); struct hash *wrapperHash = hashNew(0); -struct facetedTable *ft = facetedTableNew("the original", trackName); - -/* Write out html to pull in the other files we use. */ -facetedTableWebInit(); +struct facetedTable *ft = facetedTableFromTable(table, + trackName, "organ,cell_class,stage,cell_type"); /* Working within a form we save context */ printf("
\n"); cartSaveSession(cart); +/* Process user input and get selected subtable */ +facetedTableUpdateOnClick(ft, cart); +struct fieldedTable *selected = facetedTableSelect(ft, cart); + /* Set up url that has enough context to get back to us. This is very much a work in * progress. */ char returnUrl[PATH_LEN*2]; safef(returnUrl, sizeof(returnUrl), "../cgi-bin/hgFacetedBars?%s", cartSidUrlString(cart) ); -/* Put up the big faceted search table in a new div */ - -/* Load up table from tsv file */ -char *statsFileName = "/gbdb/hg38/bbi/singleCellMerged/barChart.stats"; -char *requiredStatsFields[] = {"cluster","count","organ","cell_class","stage","cell_type"}; -struct fieldedTable *table = fieldedTableFromTabFile(statsFileName, statsFileName, - requiredStatsFields, ArraySize(requiredStatsFields)); - -/* 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); +char viewFields[256]; +safef(viewFields, sizeof(viewFields), "count,%s,mean_total", keyField); /* Set up wrappers for some of output fields */ struct wrapContext context = {.nameIx = 0, .countIx = fieldedTableFindFieldIx(table, "count"), .meanIx = fieldedTableFindFieldIx(table, "mean_total"), .colorIx = fieldedTableFindFieldIx(table, "color"), }; context.maxMean = fieldedTableMaxInCol(table, context.meanIx); /* Put up faceted search and table of visible fields. */ hashAdd(wrapperHash, "mean_total", wrapMean); -webFilteredFieldedTable(cart, selected, - "count,cluster,mean_total", returnUrl, trackName, - 32, wrapperHash, &context, - FALSE, NULL, - selected->rowCount, 7, - NULL, emptyHash, - ffArray, "organ,cell_class,stage,cell_type", - NULL); + +facetedTableWriteHtml(ft, cart, selected, viewFields, returnUrl, 32, wrapperHash, &context, 10); /* Clean up and go home. */ printf("
\n"); hashFree(&emptyHash); sqlDisconnect(&conn); } void doMiddle(struct cart *theCart) /* Set up globals and make web page */ { /* Set some major global variable and attach us to current genome and DB. */ cart = theCart; getDbAndGenome(cart, &database, &genome, oldVars); initGenbankTableNames(database);