c7723adc566681d4f69232076df356c36aa5a1cf
max
  Fri Sep 9 16:03:22 2016 -0700
adding first versin of pipeline for crispr tracks and trackDb statements supporting external extra fields, refs #17235

diff --git src/hg/hgc/hgc.c src/hg/hgc/hgc.c
index d9fc74c..f651bd5 100644
--- src/hg/hgc/hgc.c
+++ src/hg/hgc/hgc.c
@@ -780,31 +780,34 @@
 void bedPrintPos(struct bed *bed, int bedSize, struct trackDb *tdb)
 /* Print first bedSize fields of a bed type structure in
  * standard format. */
 {
 char *strand = NULL;
 if (bedSize >= 4 && bed->name[0] != 0)
     {
     char *label = "Item", *tdbLabel = NULL;
     if (tdb && ((tdbLabel = trackDbSetting(tdb, "bedNameLabel")) != NULL))
 	label = tdbLabel;
     printf("<B>%s:</B> %s<BR>\n", label, bed->name);
     }
 if (bedSize >= 5)
     {
     if (!tdb || !trackDbSetting(tdb, "noScoreFilter"))
-	printf("<B>Score:</B> %d<BR>\n", bed->score);
+        {
+        char *scoreLabel = trackDbSettingOrDefault(tdb, "scoreLabel", "Score");
+	printf("<B>%s:</B> %d<BR>\n", scoreLabel, bed->score);
+        }
     }
 if (bedSize >= 6)
    {
    strand = bed->strand;
    }
 printPos(bed->chrom, bed->chromStart, bed->chromEnd, strand, TRUE, bed->name);
 
 }
 
 void interactionPrintPos( struct bed *bed, int bedSize, struct trackDb *tdb)
 /* Print first bedSize fields of a bed type structure in
  * standard format. */
 {
 
 if (bed->blockCount == 2)
@@ -1513,97 +1516,135 @@
 	chopString(itemName, "|", parts, ArraySize(parts));
         idForUrl = parts[0];
         itemName = parts[1];
         encode = FALSE; // assume the link is already encoded
         }
 
     char *idUrl = replaceInUrl(url, idForUrl, cart, database, seqName, winStart, 
                     winEnd, tdb->track, encode);
     printf("<a href=\"%s\" target=\"_blank\">%s</a>", idUrl, itemName);
     } 
 printf("</td></tr>\n");
 freeMem(slIds);
 //freeMem(idNames);
 }
 
-int extraFieldsPrint(struct trackDb *tdb,struct sqlResult *sr,char **fields,int fieldCount)
-// Any extra bed or bigBed fields (defined in as and occurring after N in bed N + types.
-// sr may be null for bigBeds.
-// Returns number of extra fields actually printed.
+int extraFieldsStart(struct trackDb *tdb, int fieldCount, struct asObject *as)
+/* return the index of the first extra field */
 {
-struct sqlConnection *conn = NULL ;
-if (!trackHubDatabase(database))
-    conn = hAllocConnTrack(database, tdb);
-struct asObject *as = asForTdb(conn, tdb);
-hFreeConn(&conn);
-if (as == NULL)
-    return 0;
-
-// We are trying to print extra fields so we need to figure out how many fields to skip
 int start = 0;
 char *type = cloneString(tdb->type);
 char *word = nextWord(&type);
 if (word && (sameWord(word,"bed") || sameWord(word,"bigBed") || sameWord(word,"bigGenePred")))
     {
     if (NULL != (word = nextWord(&type)))
         start = sqlUnsigned(word);
     else // custom beds and bigBeds may not have full type "begBed 9 +"
         start = max(0,slCount(as->columnList) - fieldCount);
     }
+return start;
+}
+
+struct slPair* getExtraFields(struct trackDb *tdb, char **fields, int fieldCount)
+/* return the extra field names and their values as a list of slPairs.  */
+{
+struct asObject *as = asForDb(tdb, database);
+if (as == NULL)
+    return NULL;
+struct asColumn *col = as->columnList;
+
+int start = extraFieldsStart(tdb, fieldCount, as);
+// skip past known fields
+for (;start !=0 && col != NULL;col=col->next)
+    if (start > 0)
+        start--;
+
+struct slPair *extraFields = 0;
 int count = 0;
+for (;col != NULL && count < fieldCount;col=col->next)
+    {
+    struct slPair *slp;
+    AllocVar(slp);
+    char *fieldName = col->name;
+    char *fieldVal = fields[count];
+    slp->name = fieldName;
+    slp->val = fieldVal;
+    slAddHead(&extraFields, slp);
+    count++;
+    //printf("name %s, val %s, idx %d<br>", fieldName, fieldVal, count);
+    }
+slReverse(extraFields);
+return extraFields;
+}
+
+int extraFieldsPrint(struct trackDb *tdb,struct sqlResult *sr,char **fields,int fieldCount)
+// Any extra bed or bigBed fields (defined in as and occurring after N in bed N + types.
+// sr may be null for bigBeds.
+// Returns number of extra fields actually printed.
+{
+struct asObject *as = asForDb(tdb, database);
+if (as == NULL)
+    return 0;
+
+// We are trying to print extra fields so we need to figure out how many fields to skip
+int start = extraFieldsStart(tdb, fieldCount, as);
+
 struct asColumn *col = as->columnList;
 char *urlsStr = trackDbSetting(tdb, "urls");
 struct hash* fieldToUrl = hashFromString(urlsStr);
 boolean skipEmptyFields = trackDbSettingOn(tdb, "skipEmptyFields");
 
 // make list of fields to skip
 char *skipFieldsStr = trackDbSetting(tdb, "skipFields");
 struct slName *skipIds = NULL;
 if (skipFieldsStr)
     skipIds = slNameListFromComma(skipFieldsStr);
 
 // make list of fields that are separated from other fields
 char *sepFieldsStr = trackDbSetting(tdb, "sepFields");
 struct slName *sepFields = NULL;
 if (sepFieldsStr)
     sepFields = slNameListFromComma(sepFieldsStr);
 
 // iterate over fields, print as table rows
+int count = 0;
 for (;col != NULL && count < fieldCount;col=col->next)
     {
     if (start > 0)  // skip past already known fields
         {
         start--;
         continue;
         }
     int ix = count;
     if (sr != NULL)
         {
         ix = sqlFieldColumn(sr, col->name); // If sr provided, name must match sql columnn name!
         if (ix == -1 || ix > fieldCount)      // so extraField really just provides a label
             continue;
         }
 
     char *fieldName = col->name;
 
     if (count == 0)
         printf("<br><table class='bedExtraTbl'>");
     
     count++;
 
     // do not print a row if the fieldName from the .as file is in the "skipFields" list
-    if (skipIds && slNameInList(skipIds, fieldName))
+    // or if a field name starts with _. This maked bigBed extra fields consistent with
+    // external extra fields in that _ field names have some meaning and are not shown
+    if (startsWith("_", fieldName) || (skipIds && slNameInList(skipIds, fieldName)))
         continue;
 
     // skip this row if it's empty and "skipEmptyFields" option is set
     if (skipEmptyFields && isEmpty(fields[ix]))
         continue;
 
     // split this table to separate current row from the previous one, if the trackDb option is set
     if (sepFields && slNameInList(sepFields, fieldName))
         printf("</tr></table>\n<p>\n<table class='bedExtraTbl'>");
 
     // field description
     char *entry;
     if (sameString(fieldName, "cdsStartStat") && sameString("enum('none','unk','incmpl','cmpl')", col->comment))
         entry = "Status of CDS start annotation (none, unknown, incomplete, or complete)";
     else if (sameString(fieldName, "cdsEndStat") && sameString("enum('none','unk','incmpl','cmpl')", col->comment))
@@ -1667,30 +1708,31 @@
 while ((row = sqlNextRow(sr)) != NULL)
     {
     if (firstTime)
 	firstTime = FALSE;
     else
 	htmlHorizontalLine();
     bed = bedLoadN(row+hasBin, bedSize);
     if ((tdb->type != NULL) && sameString(tdb->type, "interaction"))
 	{
 	interactionPrintPos( bed, bedSize, tdb);
         }
     else
         bedPrintPos(bed, bedSize, tdb);
 
     extraFieldsPrint(tdb,sr,row,sqlCountColumns(sr));
+
     // check for seq1 and seq2 in columns 7+8 (eg, pairedTagAlign)
     char *setting = trackDbSetting(tdb, BASE_COLOR_USE_SEQUENCE);
     if (bedSize == 6 && setting && sameString(setting, "seq1Seq2"))
 	printf("<br><B>Sequence 1:</B> %s<br><B>Sequence 2:</B> %s<br>\n",row[hasBin+6], row[hasBin+7]);
     printCompareGenomeLinks(tdb,bed->name);
     }
 sqlFreeResult(&sr);
 getBedTopScorers(conn, tdb, table, item, start, bedSize);
 printItemDetailsHtml(tdb, item);
 }
 
 #define INTRON 10
 #define CODINGA 11
 #define CODINGB 12
 #define UTR5 13