/* compositeTrack -- handle composite tracks / subtrack merge. */ #include "common.h" #include "linefile.h" #include "hash.h" #include "portable.h" #include "cheapcgi.h" #include "cart.h" #include "jksql.h" #include "trackDb.h" #include "bed.h" #include "hdb.h" #include "hui.h" #include "hgTables.h" /* We keep two copies of variables, so that we can * cancel out of the page. */ static char *curVars[] = {hgtaSubtrackMergePrimary, hgtaSubtrackMergeOp, hgtaSubtrackMergeMoreThreshold, hgtaSubtrackMergeLessThreshold, hgtaSubtrackMergeWigOp, hgtaSubtrackMergeRequireAll, hgtaSubtrackMergeUseMinScore, hgtaSubtrackMergeMinScore, }; static char *nextVars[] = {hgtaNextSubtrackMergePrimary, hgtaNextSubtrackMergeOp, hgtaNextSubtrackMergeMoreThreshold, hgtaNextSubtrackMergeLessThreshold, hgtaNextSubtrackMergeWigOp, hgtaNextSubtrackMergeRequireAll, hgtaNextSubtrackMergeUseMinScore, hgtaNextSubtrackMergeMinScore, }; boolean anySubtrackMerge(char *db, char *table) /* Return TRUE if a subtrack merge has been specified on db.table. */ { char *smp = cartOptionalString(cart, hgtaSubtrackMergePrimary); if (smp == NULL) return FALSE; else { char *dbTable = getDbTable(db, table); boolean curTableHasMerge = sameString(smp, dbTable); freez(&dbTable); return curTableHasMerge; } } boolean subtrackMergeIsBpWise() /* Return TRUE if the subtrack merge operation is base pair-wise. */ { char *op = cartUsualString(cart, hgtaSubtrackMergeOp, "any"); return (sameString(op, "and") || sameString(op, "or")); } boolean isSubtrackMerged(char *tableName) /* Return true if tableName has been selected for subtrack merge. */ { char option[128]; safef(option, sizeof(option), "%s_sel", tableName); return cartUsualBoolean(cart, option, FALSE); } static void makeWigOpButton(char *val, char *selVal) /* Make merge-wiggle-op radio button. */ { cgiMakeRadioButton(hgtaNextSubtrackMergeWigOp, val, sameString(val, selVal)); } static void showWiggleMergeOptions() /* Show subtrack merge operation options for wiggle/bedGraph tables. */ { char *setting = cartUsualString(cart, hgtaNextSubtrackMergeWigOp, "average"); makeWigOpButton("average", setting); printf("Average (at each position) of all selected subtracks' scores
\n"); makeWigOpButton("sum", setting); printf("Sum (at each position) of all selected subtracks' scores
\n"); makeWigOpButton("product", setting); printf("Product (at each position) of all selected subtracks' scores
\n"); makeWigOpButton("min", setting); printf("Minimum (at each position) of all selected subtracks' scores
\n"); makeWigOpButton("max", setting); printf("Maximum (at each position) of all selected subtracks' scores

\n"); cgiMakeCheckBox(hgtaNextSubtrackMergeRequireAll, cartUsualBoolean(cart, hgtaSubtrackMergeRequireAll, FALSE)); printf("Discard scores for positions at which one or more selected subtracks " "have no data.
\n"); cgiMakeCheckBox(hgtaNextSubtrackMergeUseMinScore, cartUsualBoolean(cart, hgtaSubtrackMergeUseMinScore, FALSE)); printf("Discard scores less than \n"); setting = cartCgiUsualString(cart, hgtaNextSubtrackMergeMinScore, "0.0"); cgiMakeTextVar(hgtaNextSubtrackMergeMinScore, setting, 5); printf(" after performing the above operation.

\n"); } static void makeOpButton(char *val, char *selVal) /* Make merge-bed-op radio button. */ { cgiMakeRadioButton(hgtaNextSubtrackMergeOp, val, sameString(val, selVal)); } static void showBedMergeOptions() /* Show subtrack merge operation options for tables that are distilled * to BED (not wiggle/bedGraph). */ { char *op = cartUsualString(cart, hgtaNextSubtrackMergeOp, "any"); char *setting = NULL; hPrintf("These combinations will maintain the gene/alignment structure " "(if any) of %s:

\n", curTable); makeOpButton("any", op); printf("All %s records that have any overlap with any other selected subtrack
\n", curTable); makeOpButton("none", op); printf("All %s records that have no overlap with any other selected subtrack
\n", curTable); makeOpButton("more", op); printf("All %s records that have at least ", curTable); setting = cartCgiUsualString(cart, hgtaNextSubtrackMergeMoreThreshold, "80"); cgiMakeTextVar(hgtaNextSubtrackMergeMoreThreshold, setting, 3); printf(" %% overlap with any other selected subtrack
\n"); makeOpButton("less", op); printf("All %s records that have at most ", curTable); setting = cartCgiUsualString(cart, hgtaNextSubtrackMergeLessThreshold, "80"); cgiMakeTextVar(hgtaNextSubtrackMergeLessThreshold, setting, 3); printf(" %% overlap with any other selected subtrack
\n"); makeOpButton("cat", op); printf("All %s records, as well as all records from all other selected subtracks

\n", curTable); printf("These combinations will discard the gene/alignment structure (if any) " "of %s and produce a simple list of position ranges.

\n", curTable); makeOpButton("and", op); printf("Base-pair-wise intersection (AND) of %s and other selected subtracks
\n", curTable); makeOpButton("or", op); printf("Base-pair-wise union (OR) of %s and other selected subtracks

\n", curTable); } void doSubtrackMergeMore(struct sqlConnection *conn) /* Respond to subtrack merge create/edit button */ { char *dbTable = getDbTable(database, curTable); htmlOpen("Merge subtracks of %s (%s)", curTrack->table, curTrack->longLabel); hPrintf("

\n", cartUsualString(cart, "formMethod", "POST")); cartSaveSession(cart); /* Currently selected subtrack table will be the primary subtrack in the * merge. */ cgiMakeHiddenVar(hgtaNextSubtrackMergePrimary, dbTable); hPrintf("

Select a subset of subtracks to merge:

\n"); hCompositeUi(database, cart, curTrack, curTable, hgtaDoSubtrackMergePage, "mainForm"); hPrintf("

Select a merge operation:

\n"); struct trackDb *primary = subTdbFind(curTrack,curTable); if (isWiggle(database, curTable) || isBedGraph(curTable) || isBigWigTable(curTable)) showWiggleMergeOptions(primary->longLabel); else showBedMergeOptions(); hPrintf("If a filter is specified on the main Table Browser page, it will " "be applied only to %s, not to any other selected subtrack. ", primary->longLabel); hPrintf("If an intersection is specified on the main page, it will be applied " "to the result of this merge.

\n"); hPrintf("

\n"); cgiMakeButton(hgtaDoSubtrackMergeSubmit, "submit"); hPrintf(" "); cgiMakeButton(hgtaDoMainPage, "cancel"); hPrintf("

\n"); htmlClose(); } char *describeSubtrackMerge(char *linePrefix) /* Return a multi-line string that describes the specified subtrack merge, * with each line beginning with linePrefix. */ { struct dyString *dy = dyStringNew(512); struct trackDb *primary = subTdbFind(curTrack,curTable), *tdb = NULL; dyStringAppend(dy, linePrefix); dyStringPrintf(dy, "Subtrack merge, primary table = %s (%s)\n", curTable, primary->longLabel); dyStringAppend(dy, linePrefix); dyStringPrintf(dy, "Subtrack merge operation: "); if (isWiggle(database, curTable) || isBedGraph(curTable) || isBigWigTable(curTable)) { char *op = cartString(cart, hgtaSubtrackMergeWigOp); dyStringPrintf(dy, "%s of %s and selected subtracks:\n", op, curTable); } else { char *op = cartString(cart, hgtaSubtrackMergeOp); if (sameString(op, "any")) dyStringPrintf(dy, "All %s records that have any overlap with " "any other selected subtrack:\n", curTable); else if (sameString(op, "none")) dyStringPrintf(dy, "All %s records that have no overlap with " "any other selected subtrack:\n", curTable); else if (sameString(op, "more")) { dyStringPrintf(dy, "All %s records that have at least %s ", curTable, cartString(cart, hgtaNextSubtrackMergeMoreThreshold)); dyStringPrintf(dy, " %% overlap with any other selected subtrack:\n"); } else if (sameString(op, "less")) { dyStringPrintf(dy, "All %s records that have at most %s ", curTable, cartString(cart, hgtaNextSubtrackMergeLessThreshold)); dyStringPrintf(dy, " %% overlap with any other selected subtrack:\n"); } else if (sameString(op, "cat")) dyStringPrintf(dy, "All %s records, as well as all records from " "all other selected subtracks:\n", curTable); else if (sameString(op, "and")) dyStringPrintf(dy, "Base-pair-wise intersection (AND) of %s and " "other selected subtracks:\n", curTable); else if (sameString(op, "or")) dyStringPrintf(dy, "Base-pair-wise union (OR) of %s and other " "selected subtracks:\n", curTable); else errAbort("describeSubtrackMerge: unrecognized op %s", op); } struct slRef *tdbRef, *tdbRefList = trackDbListGetRefsToDescendantLeaves(curTrack->subtracks); for (tdbRef = tdbRefList; tdbRef != NULL; tdbRef = tdbRef->next) { tdb = tdbRef->val; if (!sameString(tdb->table, curTable) && isSubtrackMerged(tdb->table) && sameString(tdb->type, primary->type)) { dyStringAppend(dy, linePrefix); dyStringPrintf(dy, " %s (%s)\n", tdb->table, tdb->longLabel); } } return dyStringCannibalize(&dy); } static void copyCartVars(struct cart *cart, char **source, char **dest, int count) /* Copy from source to dest (arrays of cart variable names). */ { int i; for (i=0; i