bf229bca8bf92e11feb9aa64a52a90974fc2f375
braney
Wed Sep 27 12:09:42 2017 -0700
clean up C code, add support for supertracks in Available Tracks
diff --git src/hg/hgCollection/hgCollection.c src/hg/hgCollection/hgCollection.c
index 2b230cb..d0f48b3 100644
--- src/hg/hgCollection/hgCollection.c
+++ src/hg/hgCollection/hgCollection.c
@@ -9,88 +9,55 @@
#include "hubConnect.h"
#include "hui.h"
#include "grp.h"
#include "cheapcgi.h"
#include "jsHelper.h"
#include "web.h"
#include "knetUdc.h"
#include "api.h"
#include "genbank.h"
#include "htmshell.h"
#include "jsonParse.h"
#include "customComposite.h"
#include "stdlib.h"
/* Global Variables */
-struct cart *cart; /* CGI and other variables */
struct hash *oldVars = NULL; /* The cart before new cgi stuff added. */
-char *genome = NULL; /* Name of genome - mouse, human, etc. */
-char *database = NULL; /* Current genome database - hg17, mm5, etc. */
-char *regionType = NULL; /* genome, ENCODE pilot regions, or specific position range. */
-struct grp *fullGroupList = NULL; /* List of all groups. */
-struct trackDb *fullTrackList = NULL; /* List of all tracks in database. */
- struct pipeline *compressPipeline = (struct pipeline *)NULL;
-
-
// Null terminated list of CGI Variables we don't want to save permanently:
char *excludeVars[] = {"Submit", "submit", "hgva_startQuery", "jsonp", NULL,};
struct track
{
struct track *next;
struct track *trackList;
struct trackDb *tdb;
char *name;
char *shortLabel;
char *longLabel;
char *visibility;
unsigned long color;
char *viewFunc;
};
struct trackDbRef
{
struct trackDbRef *next;
struct trackDb *tdb;
int order;
};
-char *getString(char **input)
-// grab a quoted string out of text blob
-{
-char *ptr = *input;
-
-if (*ptr != '"')
- errAbort("string must start with \"");
-ptr++;
-char *ret = ptr;
-for(; *ptr != '"'; ptr++)
- ;
-*ptr = 0;
-ptr++;
-
-if (*ptr == ',')
- ptr++;
-
-if (startsWith("coll_", ret))
- ret = ret + 5;
-
-*input = ptr;
-return ret;
-}
-
-char *makeUnique(struct hash *nameHash, char *name)
+static char *makeUnique(struct hash *nameHash, char *name)
// Make the name of this track unique.
{
char *skipHub = trackHubSkipHubName(name);
if (hashLookup(nameHash, skipHub) == NULL)
{
hashStore(nameHash, name);
return skipHub;
}
unsigned count = 0;
char buffer[4096];
for(;; count++)
{
safef(buffer, sizeof buffer, "%s%d", skipHub, count);
@@ -163,31 +130,31 @@
jsInlineF("");
}
static void outHubHeader(FILE *f, char *db, char *hubName)
// output a track hub header
{
fprintf(f,"hub hub1\n\
shortLabel User Composite\n\
longLabel User Composite\n\
useOneFile on\n\
email genome-www@soe.ucsc.edu\n\n");
fprintf(f,"genome %s\n\n", db);
}
-static char *getHubName(char *db)
+static char *getHubName(struct cart *cart, char *db)
// get the name of the hub to use for user collections
{
struct tempName hubTn;
char buffer[4096];
safef(buffer, sizeof buffer, "%s-%s", customCompositeCartName, db);
char *hubName = cartOptionalString(cart, buffer);
if (hubName == NULL)
{
trashDirDateFile(&hubTn, "hgComposite", "hub", ".txt");
hubName = cloneString(hubTn.forCgi);
cartSetString(cart, buffer, hubName);
FILE *f = mustOpen(hubName, "a");
outHubHeader(f, db, hubName);
fclose(f);
@@ -203,176 +170,178 @@
bool enabled = TRUE;
char *words[2];
char *setting;
if ((setting = trackDbLocalSetting(subTdb, "parent")) != NULL)
{
if (chopLine(cloneString(setting), words) >= 2)
if (sameString(words[1], "off"))
enabled = FALSE;
}
else
return subTdb->visibility != tvHide;
return enabled;
}
-bool isSubtrackVisible(struct trackDb *tdb)
+static bool isSubtrackVisible(struct cart *cart, struct trackDb *tdb)
/* Has this subtrack not been deselected in hgTrackUi or declared with
* * "subTrack ... off"? -- assumes composite track is visible. */
{
boolean overrideComposite = (NULL != cartOptionalString(cart, tdb->track));
bool enabledInTdb = subtrackEnabledInTdb(tdb);
char option[1024];
safef(option, sizeof(option), "%s_sel", tdb->track);
boolean enabled = cartUsualBoolean(cart, option, enabledInTdb);
if (overrideComposite)
enabled = TRUE;
return enabled;
}
-bool isParentVisible( struct trackDb *tdb)
+static bool isParentVisible(struct cart *cart, struct trackDb *tdb)
// Are this track's parents visible?
{
if (tdb->parent == NULL)
return TRUE;
-if (!isParentVisible(tdb->parent))
+if (!isParentVisible(cart, tdb->parent))
return FALSE;
char *cartVis = cartOptionalString(cart, tdb->parent->track);
boolean vis;
if (cartVis != NULL)
vis = differentString(cartVis, "hide");
else if (tdbIsSuperTrack(tdb->parent))
vis = tdb->parent->isShow;
else
vis = tdb->parent->visibility != tvHide;
return vis;
}
-void checkForVisible(struct trackDbRef **list, struct trackDb *tdb)
+static void checkForVisible(struct cart *cart, struct trackDbRef **list, struct trackDb *tdb)
/* Walk the trackDb hierarchy looking for visible leaf tracks. */
{
struct trackDb *subTdb;
char buffer[4096];
if (tdb->subtracks)
{
for(subTdb = tdb->subtracks; subTdb; subTdb = subTdb->next)
- checkForVisible(list, subTdb);
+ checkForVisible(cart, list, subTdb);
}
else
{
- if (isParentVisible(tdb) && isSubtrackVisible(tdb))
+ if (isParentVisible(cart, tdb) && isSubtrackVisible(cart, tdb))
{
struct trackDbRef *tdbRef;
AllocVar(tdbRef);
tdbRef->tdb = tdb;
slAddHead(list, tdbRef);
safef(buffer, sizeof buffer, "%s_imgOrd", tdb->track);
tdbRef->order = cartUsualInt(cart, buffer, 0);
}
}
}
-int tdbRefCompare (const void *va, const void *vb)
+static int tdbRefCompare (const void *va, const void *vb)
// Compare to sort on imgTrack->order.
{
const struct trackDbRef *a = *((struct trackDbRef **)va);
const struct trackDbRef *b = *((struct trackDbRef **)vb);
return (a->order - b->order);
}
-void addVisibleTracks()
+static void addVisibleTracks(struct cart *cart, struct trackDb *trackList)
// add the visible tracks table rows.
{
struct trackDb *tdb;
struct trackDbRef *tdbRefList = NULL, *tdbRef;
//checkForVisible(fullTrackList);
-for(tdb = fullTrackList; tdb; tdb = tdb->next)
+for(tdb = trackList; tdb; tdb = tdb->next)
{
- checkForVisible(&tdbRefList, tdb);
+ checkForVisible(cart, &tdbRefList, tdb);
}
slSort(&tdbRefList, tdbRefCompare);
jsInlineF("
");
jsInlineF("- %s", "visibile", "Visible Tracks");
jsInlineF("
");
for(tdbRef = tdbRefList; tdbRef; tdbRef = tdbRef->next)
printGroup("visible", tdbRef->tdb, FALSE, FALSE);
jsInlineF("
");
jsInlineF(" ");
jsInlineF("
");
}
-void doTable()
+static void doTable(struct cart *cart, char *db, struct grp *groupList, struct trackDb *trackList)
// output the tree table
{
-char *hubName = hubNameFromUrl(getHubName(database));
+char *hubName = hubNameFromUrl(getHubName(cart, db));
struct grp *curGroup;
-for(curGroup = fullGroupList; curGroup; curGroup = curGroup->next)
+for(curGroup = groupList; curGroup; curGroup = curGroup->next)
{
if ((hubName != NULL) && sameString(curGroup->name, hubName))
break;
}
if (curGroup != NULL)
{
// print out all the tracks in this group
struct trackDb *tdb;
jsInlineF("$('#currentCollection').append(\"");
- for(tdb = fullTrackList; tdb; tdb = tdb->next)
+ for(tdb = trackList; tdb; tdb = tdb->next)
{
if (sameString(tdb->grp, hubName))
{
jsInlineF("", trackHubSkipHubName(tdb->track), tdb->shortLabel);
jsInlineF("
");
printGroup("collections", tdb, TRUE, TRUE);
jsInlineF("
");
jsInlineF("
");
+ printf("ignoring %s\n", tdb->track);
+ continue;
}
}
jsInlineF("\");\n");
// print out all the tracks in this group
jsInlineF("$('#collectionList').append(\"");
- for(tdb = fullTrackList; tdb; tdb = tdb->next)
+ for(tdb = trackList; tdb; tdb = tdb->next)
{
if (sameString(tdb->grp, hubName))
{
jsInlineF("%s", trackHubSkipHubName(tdb->track),trackHubSkipHubName(tdb->track), tdb->shortLabel);
//printGroup("collections", tdb, TRUE, TRUE);
}
}
jsInlineF("\");\n");
}
jsInlineF("$('#tracks').append(\"");
-addVisibleTracks();
-for(curGroup = fullGroupList; curGroup; curGroup = curGroup->next)
+addVisibleTracks(cart, trackList);
+for(curGroup = groupList; curGroup; curGroup = curGroup->next)
{
if ((hubName != NULL) && sameString(curGroup->name, hubName))
continue;
jsInlineF("");
jsInlineF("- %s", curGroup->name, curGroup->label );
struct trackDb *tdb;
jsInlineF("
");
- for(tdb = fullTrackList; tdb; tdb = tdb->next)
+ for(tdb = trackList; tdb; tdb = tdb->next)
{
if ( sameString(tdb->grp, curGroup->name))
{
printGroup(curGroup->name, tdb, FALSE, FALSE);
}
}
jsInlineF("
");
jsInlineF(" ");
jsInlineF("
");
}
jsInlineF("\");\n");
jsInlineF("hgCollection.init();\n");
}
@@ -405,82 +374,65 @@
puts(
" \n"
"
\n");
puts("
");
puts("
");
webIncludeHelpFileSubst("hgCollectionHelp", NULL, FALSE);
puts("
");
puts("
");
puts(
"
\n"
"
\n");
}
-void doMainPage()
+static void doMainPage(struct cart *cart, char *db, struct grp *groupList, struct trackDb *trackList)
/* Print out initial HTML of control page. */
{
-webStartGbNoBanner(cart, database, "Collections");
+webStartGbNoBanner(cart, db, "Collections");
webIncludeResourceFile("gb.css");
webIncludeResourceFile("spectrum.min.css");
webIncludeResourceFile("hgGtexTrackSettings.css");
webIncludeFile("inc/hgCollection.html");
printHelp();
-doTable();
+doTable(cart, db, groupList, trackList);
puts("");
puts("");
//puts("");
puts("");
puts("\n");
jsIncludeFile("utils.js", NULL);
jsIncludeFile("ajax.js", NULL);
jsIncludeFile("spectrum.min.js", NULL);
jsIncludeFile("hgCollection.js", NULL);
webEndGb();
}
static char *getSqlBigWig(struct sqlConnection *conn, char *db, struct trackDb *tdb)
// figure out the bigWig for native tables
{
char buffer[4096];
safef(buffer, sizeof buffer, "NOSQLINJ select fileName from %s", tdb->table);
return sqlQuickString(conn, buffer);
}
-char *getUrl(struct sqlConnection *conn, char *db, struct track *track, struct hash *nameHash)
-// get the bigDataUrl for a track
-{
-struct trackDb *tdb = hashMustFindVal(nameHash, track->name);
-
-if (tdb == NULL)
- errAbort("cannot find trackDb for %s\n", track->name);
-
-char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl");
-if (bigDataUrl == NULL)
- {
- if (startsWith("bigWig", tdb->type))
- bigDataUrl = getSqlBigWig(conn, db, tdb);
- }
-return bigDataUrl;
-}
-
-void outTdb(struct sqlConnection *conn, char *db, FILE *f, char *name, struct trackDb *tdb, char *parent, char *visibility, unsigned int color, struct track *track, struct hash *nameHash, struct hash *collectionNameHash, int numTabs, int priority)
+static void outTdb(struct sqlConnection *conn, char *db, FILE *f, char *name, struct trackDb *tdb, char *parent, char *visibility, unsigned int color, struct track *track, struct hash *nameHash, struct hash *collectionNameHash, int numTabs, int priority)
// out the trackDb for one track
{
char *dataUrl = NULL;
char *bigDataUrl = trackDbSetting(tdb, "bigDataUrl");
char *tabs = "\t";
if (numTabs == 2)
tabs = "\t\t";
if (bigDataUrl == NULL)
{
if (startsWith("bigWig", tdb->type))
dataUrl = getSqlBigWig(conn, db, tdb);
}
struct hashCookie cookie = hashFirst(tdb->settingsHash);
struct hashEl *hel;
@@ -511,35 +463,30 @@
char *shortLabel = collection->shortLabel;
char *longLabel = collection->longLabel;
fprintf(f,"track %s\n\
shortLabel %s\n\
compositeTrack on\n\
autoScale on\n\
longLabel %s\n\
%s on\n\
color %ld,%ld,%ld \n\
type wig \n\
visibility full\n\n", parent, shortLabel, longLabel, CUSTOM_COMPOSITE_SETTING,
0xff& (collection->color >> 16),0xff& (collection->color >> 8),0xff& (collection->color));
}
-int snakePalette2[] =
-{
-0x1f77b4, 0xaec7e8, 0xff7f0e, 0xffbb78, 0x2ca02c, 0x98df8a, 0xd62728, 0xff9896, 0x9467bd, 0xc5b0d5, 0x8c564b, 0xc49c94, 0xe377c2, 0xf7b6d2, 0x7f7f7f, 0xc7c7c7, 0xbcbd22, 0xdbdb8d, 0x17becf, 0x9edae5
-};
-
static char *skipColl(char *str)
{
if (startsWith("coll_", str))
return &str[5];
return str;
}
static int outView(FILE *f, struct sqlConnection *conn, char *db, struct track *view, char *parent, struct hash *nameHash, struct hash *collectionNameHash, int priority)
// output a view to a trackhub
{
fprintf(f,"\ttrack %s\n\
\tshortLabel %s\n\
\tlongLabel %s\n\
\tview %s \n\
\tcontainer mathWig\n\
@@ -553,34 +500,34 @@
fprintf(f, "\n");
//int useColor = 0;
struct track *track = view->trackList;
for(; track; track = track->next)
{
struct trackDb *tdb = hashMustFindVal(nameHash, skipColl(track->name));
outTdb(conn, db, f, skipColl(track->name),tdb, view->name, track->visibility, track->color, track, nameHash, collectionNameHash, 2, priority++);
//useColor++;
}
return priority;
}
-void updateHub(char *db, struct track *collectionList, struct hash *nameHash)
+static void updateHub(struct cart *cart, char *db, struct track *collectionList, struct hash *nameHash)
// save our state to the track hub
{
-char *hubName = getHubName(db);
+char *hubName = getHubName(cart, db);
chmod(hubName, 0666);
FILE *f = mustOpen(hubName, "w");
struct hash *collectionNameHash = newHash(6);
outHubHeader(f, db, hubName);
//int useColor = 0;
struct track *collection;
struct sqlConnection *conn = hAllocConn(db);
for(collection = collectionList; collection; collection = collection->next)
{
outComposite(f, collection);
struct trackDb *tdb;
struct track *track;
int priority = 1;
@@ -595,49 +542,49 @@
tdb = hashMustFindVal(nameHash, track->name);
outTdb(conn, db, f, track->name,tdb, collection->name, track->visibility, track->color, track, nameHash, collectionNameHash, 1, priority++);
/*
useColor++;
if (useColor == (sizeof snakePalette2 / sizeof(int)))
useColor = 0;
*/
}
}
}
fclose(f);
hFreeConn(&conn);
}
-unsigned long hexStringToLong(char *str)
+static unsigned long hexStringToLong(char *str)
{
/*
char buffer[1024];
strcpy(buffer, "0x");
strcat(buffer, &str[1]);
*/
return strtol(&str[1], NULL, 16);
}
struct jsonParseData
{
struct track **collectionList;
struct hash *trackHash;
};
-void jsonObjStart(struct jsonElement *ele, char *name,
+static void jsonObjStart(struct jsonElement *ele, char *name,
boolean isLast, void *context)
{
struct jsonParseData *jpd = (struct jsonParseData *)context;
struct track **collectionList = jpd->collectionList;
struct hash *trackHash = jpd->trackHash;
struct track *track;
if ((name == NULL) && (ele->type == jsonObject))
{
struct hash *objHash = jsonObjectVal(ele, "name");
struct jsonElement *parentEle = hashFindVal(objHash, "id");
char *parentId = jsonStringEscape(parentEle->val.jeString);
parentEle = hashFindVal(objHash, "parent");
char *parentName = jsonStringEscape(parentEle->val.jeString);
@@ -674,38 +621,38 @@
}
}
static struct track *parseJsonElements( struct jsonElement *collectionElements)
// parse the JSON returned from the ap
{
struct track *collectionList = NULL;
struct hash *trackHash = hashNew(5);
struct jsonParseData jpd = {&collectionList, trackHash};
jsonElementRecurse(collectionElements, NULL, FALSE, jsonObjStart, NULL, &jpd);
slReverse(&collectionList);
return collectionList;
}
-void doAjax(char *db, char *jsonText, struct hash *nameHash)
+static void doAjax(struct cart *cart, char *db, char *jsonText, struct hash *nameHash)
// Save our state
{
cgiDecodeFull(jsonText, jsonText, strlen(jsonText));
struct jsonElement *collectionElements = jsonParse(jsonText);
struct track *collectionList = parseJsonElements(collectionElements);
-updateHub(db, collectionList, nameHash);
+updateHub(cart, db, collectionList, nameHash);
}
static void buildNameHash(struct hash *nameHash, struct trackDb *list)
{
if (list == NULL)
return;
struct trackDb *tdb = list;
for(tdb = list; tdb; tdb = tdb->next)
{
hashAdd(nameHash, trackHubSkipHubName(tdb->track), tdb);
buildNameHash(nameHash, tdb->subtracks);
}
}
@@ -748,63 +695,97 @@
*fullTrackList = traverseTree(*fullTrackList, groupHash);
struct grp *newGroupList = NULL, *grp, *nextGrp;
for (grp = *fullGroupList; grp; grp = nextGrp)
{
nextGrp = grp->next;
if (hashLookup(groupHash, grp->name))
slAddHead(&newGroupList, grp);
}
slReverse(&newGroupList);
*fullGroupList = newGroupList;
}
-void doMiddle(struct cart *theCart)
+static struct trackDb *addSupers(struct trackDb *trackList)
+/* Insert supertracks into the hierarchy. */
+{
+struct trackDb *newList = NULL;
+struct trackDb *tdb, *nextTdb;
+struct hash *superHash = newHash(5);
+
+for(tdb = trackList; tdb; tdb = nextTdb)
+ {
+ nextTdb = tdb->next;
+
+ if (tdb->parent)
+ {
+ // part of a super track
+ if (hashLookup(superHash, tdb->parent->track) == NULL)
+ {
+ hashStore(superHash, tdb->parent->track);
+
+ slAddHead(&newList, tdb->parent);
+ }
+ slAddHead(&tdb->parent->subtracks, tdb);
+ }
+ else
+ slAddHead(&newList, tdb);
+ }
+
+slReverse(&newList);
+
+return newList;
+}
+
+static void doMiddle(struct cart *cart)
/* Set up globals and make web page */
{
-cart = theCart;
-getDbAndGenome(cart, &database, &genome, oldVars);
+char *db;
+char *genome;
+getDbAndGenome(cart, &db, &genome, oldVars);
int timeout = cartUsualInt(cart, "udcTimeout", 300);
if (udcCacheTimeout() < timeout)
udcSetCacheTimeout(timeout);
knetUdcInstall();
-cartTrackDbInit(cart, &fullTrackList, &fullGroupList, TRUE);
-pruneTrackList(&fullTrackList, &fullGroupList);
+
+struct trackDb *trackList;
+struct grp *groupList;
+cartTrackDbInit(cart, &trackList, &groupList, TRUE);
+pruneTrackList(&trackList, &groupList);
+
+struct trackDb *superList = addSupers(trackList);
struct hash *nameHash = newHash(5);
-buildNameHash(nameHash, fullTrackList);
+buildNameHash(nameHash, superList);
char *jsonIn = cgiUsualString("jsonp", NULL);
fprintf(stderr, "BRANEY %s\n", jsonIn);
if (jsonIn != NULL)
{
- doAjax(database, jsonIn, nameHash);
+ doAjax(cart, db, jsonIn, nameHash);
apiOut("{\"serverSays\": \"Collections saved successfully.\"}", NULL);
}
else
{
- doMainPage();
+ doMainPage(cart, db, groupList, superList);
}
}
int main(int argc, char *argv[])
/* Process command line. */
{
long enteredMainTime = clock1000();
-
-initGenbankTableNames(database);
-
cgiSpoof(&argc, argv);
boolean isCommandLine = (cgiOptionalString("cgiSpoof") != NULL);
if (!isCommandLine)
htmlPushEarlyHandlers(); /* Make errors legible during initialization. */
oldVars = hashNew(10);
cartEmptyShellNoContent(doMiddle, hUserCookie(), excludeVars, oldVars);
if (! isCommandLine)
cgiExitTime("hgCollection", enteredMainTime);
return 0;
}