fe1627a44ee54d0dcffd8cdd27d31f499ca6d5f6
kent
  Fri Jan 29 16:08:16 2021 -0800
Adding a function that is helpful when using facets on memory tables.

diff --git src/hg/lib/facetField.c src/hg/lib/facetField.c
index e0d3c42..a41107c 100644
--- src/hg/lib/facetField.c
+++ src/hg/lib/facetField.c
@@ -1,20 +1,21 @@
 
 #include "common.h"
 #include "hash.h"
 #include "linefile.h"
 #include "jksql.h"
+#include "fieldedTable.h"
 #include "facetField.h"
 #include "csv.h"
 
 int facetValCmpSelectCountDesc(const void *va, const void *vb)
 /* Compare two facetVal so as to sort them based on selectCount with most used first.
  * If two have same count, sort alphabetically on facet val.  */
 {
 struct facetVal *a = *((struct facetVal **)va);
 struct facetVal *b = *((struct facetVal **)vb);
 int result = b->selectCount - a->selectCount;
 if (result == 0)
     {
     result = strcmp(a->val, b->val);
     }
 return result;
@@ -105,58 +106,60 @@
 facetField->valHash = hashNew(0);
 facetField->allSelected = TRUE;  // default to all values selected
 return facetField;
 }
 
 boolean perRowFacetFields(int fieldCount, char **row, char *nullVal, struct facetField *ffArray[])
 /* Process each row of a resultset updating use and select counts. 
  * Returns TRUE if row passes selected facet values filter and should be included in the final result set. */
 {
 boolean result = FALSE;
 int totalSelectedFacets = 0;
 int facetCount = 0;  // non-NULL facet count
 int i;
 for (i=0; i<fieldCount; ++i)
     {
+    struct facetField *ff = ffArray[i];
     char *val = row[i];
     if (val == NULL)
 	val = nullVal;
     if (val != NULL)
 	{
-	facetFieldAdd(ffArray[i], val, FALSE);
-	if (ffArray[i]->currentVal->selected)
+	facetFieldAdd(ff, val, FALSE);
+	if (ff->currentVal->selected)
 	    ++totalSelectedFacets;
 	++facetCount;
 	}
     else
 	{
-	ffArray[i]->currentVal = NULL;
+	ff->currentVal = NULL;
 	}
     }
 
 if ((totalSelectedFacets == facetCount) && (facetCount > 0))
     {
     // include this row in the final resultset
     result = TRUE;
     }
 for (i=0; i<fieldCount; ++i)
     {
-    if (ffArray[i]->currentVal) // disregard null values
+    struct facetField *ff = ffArray[i];
+    if (ff->currentVal) // disregard null values
 	{
 	// disregard one's self.
-	if ((totalSelectedFacets - (int)ffArray[i]->currentVal->selected) == (facetCount - 1))
-	    ffArray[i]->currentVal->selectCount++;
+	if ((totalSelectedFacets - (int)ff->currentVal->selected) == (facetCount - 1))
+	    ff->currentVal->selectCount++;
 	    // shown on GUI to guide choosing by user
 	}
     }
 return result;
 }
 
 #define facetValStringPunc '~'
 
 char *linearizeFacetVals(struct facetField *selectedList)
 /* Linearize selected fields vals into a string. fieldVal must be selected. */
 {
 struct dyString *dy = newDyString(1024);
 struct facetField *sff = NULL;
 for (sff = selectedList; sff; sff=sff->next)
     {
@@ -278,30 +281,31 @@
     for (el=valList; el; el=el->next)
 	{
 	//uglyf("adding selected field %s val %s\n", selectedFields, el->name);
 	facetFieldAdd(ff, el->name, TRUE);
 	}
     
     *spc  = ' ';  // restore
     *spc2 = ' ';  // restore
     *end = saveEnd;
     selectedFields = end+1;
     }
 slReverse(&ffList);
 return ffList;
 }
 
+
 struct facetField *facetFieldsFromSqlTableInit(char *fields[], int fieldCount, char *selectedFields, struct facetField *ffArray[])
 /* Initialize ffList and ffArray and selected facet values */
 {
 /* Create facetField list and table. */
 struct facetField *ffList = NULL, *ff;
 int i;
 for (i=0; i<fieldCount; ++i)
     {
     ff = ffArray[i] = facetFieldNew(fields[i]);
     slAddHead(&ffList, ff);
     }
 slReverse(&ffList);
 
 /* Initialize selected facet values */
 if (selectedFields)
@@ -374,30 +378,54 @@
     if (perRowFacetFields(fieldCount, row, nullVal, ffArray))
 	++selectedRowCount;
     }
 
 facetFieldsFromSqlTableFinish(ffList, facetValCmpUseCountDesc);
 
 /* Clean up and go home */
 dyStringFree(&query);
 sqlFreeResult(&sr);
 
 if (pSelectedRowCount)
     *pSelectedRowCount = selectedRowCount;
 return ffList;
 }
 
+struct facetField *facetFieldsFromFieldedTable(struct fieldedTable *ft, char *selectedFields,
+    struct facetField *ffArray[], int *retSelectedRowCount)
+/* Get a facetField list and initialize arrays based on selected fields from table 
+ * ffArray must be big enough to hold all fields in table */
+{
+struct facetField *ffList = facetFieldsFromSqlTableInit(ft->fields, ft->fieldCount, 
+    selectedFields, ffArray);
+
+struct fieldedRow *fr;
+int selectedRowCount = 0;
+int fieldCount = ft->fieldCount;
+for (fr = ft->rowList; fr != NULL; fr = fr->next)
+    {
+    if (perRowFacetFields(fieldCount, fr->row, "", ffArray))
+	++selectedRowCount;
+    }
+
+facetFieldsFromSqlTableFinish(ffList, facetValCmpUseCountDesc);
+
+if (retSelectedRowCount != NULL)
+    *retSelectedRowCount = selectedRowCount;
+return ffList;
+}
+
 struct facetVal *facetValMajorPlusOther(struct facetVal *list, double minRatio)
 /* Return a list of only the tags that are over minRatio of total tags.
  * If there are tags that have smaller amounts than this, lump them together
  * under "other".  Returns a new list. Use slFreeList() to free the result.  */
 {
 /* Figure out total and minimum count to not be lumped into other */
 long total = 0;
 struct facetVal *tc;
 for (tc = list; tc != NULL; tc = tc->next)
     total += tc->useCount;
 long minCount = round(minRatio * total);
 
 /* Loop through and copy ones over threshold to new list, and lump rest
  * into other */
 struct facetVal *newList = NULL, *newTc;