/* hgWigText.c - functions for wiggle tracks in hgText */ #include "common.h" #include "wiggle.h" #include "hgColors.h" #include "web.h" #include "cheapcgi.h" #include "hCommon.h" #include "hgText.h" #include "hui.h" #include "customTrack.h" #include "portable.h" /* possible two sets of data could be existing */ static struct wiggleData *wigData[2] = { (struct wiggleData *)NULL, (struct wiggleData *)NULL, }; /* Droplist menu for custom track visibility: */ static char *ctWigVisMenu[] = { "hide", "dense", "full", }; static int ctWigVisMenuSize = sizeof(ctWigVisMenu)/sizeof(char *); /* Droplist menu for custom track data count: */ static char *ctWigCountMenu[] = { "10000", "100000", "1000000", }; static int ctWigCountMenuSize = sizeof(ctWigCountMenu)/sizeof(char *); struct wiggleStats *wigStatsList[2] = { (struct wiggleStats *) NULL, (struct wiggleStats *) NULL, }; struct hash *chromsDone[2]; static void printBedEl(struct bed *bedEl) { printf("%s\t%u\t%u\t%s\n", bedEl->chrom, bedEl->chromStart, bedEl->chromEnd, bedEl->name); } /********* wiggle compare functions ***********************************/ static boolean wigInRange(int tableId, double value, boolean summaryOnly, struct wiggle *wiggle) { boolean ret = FALSE; if (summaryOnly) ret = ((wiggle->lowerLimit <= wigDataConstraint[tableId][1]) && (wiggle->lowerLimit+wiggle->dataRange >= wigDataConstraint[tableId][0])); else ret = (value >= wigDataConstraint[tableId][0] && value <= wigDataConstraint[tableId][1]); return ret; } static boolean wigLessThan(int tableId, double value, boolean summaryOnly, struct wiggle *wiggle) { boolean ret = FALSE; if (summaryOnly) ret = (wiggle->lowerLimit < wigDataConstraint[tableId][0]); else ret = (value < wigDataConstraint[tableId][0]); return ret; } static boolean wigLessEqual(int tableId, double value, boolean summaryOnly, struct wiggle *wiggle) { boolean ret = FALSE; if (summaryOnly) ret = (wiggle->lowerLimit <= wigDataConstraint[tableId][0]); else ret = (value <= wigDataConstraint[tableId][0]); return ret; } static boolean wigEqual(int tableId, double value, boolean summaryOnly, struct wiggle *wiggle) { boolean ret = FALSE; if (summaryOnly) ret = ((wiggle->lowerLimit < wigDataConstraint[tableId][0]) && (wiggle->lowerLimit+wiggle->dataRange > wigDataConstraint[tableId][0])); else ret = (value == wigDataConstraint[tableId][0]); return ret; } static boolean wigNotEqual(int tableId, double value, boolean summaryOnly, struct wiggle *wiggle) { boolean ret = FALSE; if (summaryOnly) ret = ((wiggle->lowerLimit > wigDataConstraint[tableId][0]) || (wiggle->lowerLimit+wiggle->dataRange < wigDataConstraint[tableId][0])); else ret = (value != wigDataConstraint[tableId][0]); return ret; } static boolean wigGreaterEqual(int tableId, double value, boolean summaryOnly, struct wiggle *wiggle) { boolean ret = FALSE; if (summaryOnly) ret=(wiggle->lowerLimit+wiggle->dataRange >= wigDataConstraint[tableId][0]); else ret = (value >= wigDataConstraint[tableId][0]); return ret; } static boolean wigGreaterThan(int tableId, double value, boolean summaryOnly, struct wiggle *wiggle) { boolean ret = FALSE; if (summaryOnly) ret = (wiggle->lowerLimit+wiggle->dataRange > wigDataConstraint[tableId][0]); else ret = (value > wigDataConstraint[tableId][0]); return ret; } static void showConstraints(char *constraints, int tableId, boolean htmlOutput) { boolean foundSome = FALSE; if (htmlOutput) printf("

Constraints in effect: "); if ((constraints != NULL) && (constraints[0] != 0)) { foundSome = TRUE; if (htmlOutput) printf("%s\n", constraints); else printf("#\tSQL query constraint: %s\n", constraints); } if (wigConstraint[tableId]) { if (htmlOutput) if (foundSome) printf(" AND "); foundSome = TRUE; if (sameWord(wigConstraint[tableId],"in range")) { if (htmlOutput) printf("(data value %s [%g , %g])", wigConstraint[tableId], wigDataConstraint[tableId][0], wigDataConstraint[tableId][1]); else printf("#\tdata value constraint range: %s [%g , %g]\n", wigConstraint[tableId], wigDataConstraint[tableId][0], wigDataConstraint[tableId][1]); } else { if (htmlOutput) printf("(data value %s %g)", wigConstraint[tableId], wigDataConstraint[tableId][0]); else printf("#\tdata value constraint: %s %g\n", wigConstraint[tableId], wigDataConstraint[tableId][0]); } } if (htmlOutput) { if (foundSome) printf("

\n"); else printf("NONE

\n"); } } void wiggleConstraints(char *cmp, char *pat, int tableIndex) { wigConstraint[tableIndex] = cmp; wiggleCompare[tableIndex] = NULL; if (strlen(pat)>0) { if (sameWord(cmp,"in range")) { char *rangeValues[2]; char *clone = cloneString(pat); int records = 0; char *comma = strchr(pat,','); if (comma == (char *)NULL) records = chopByWhite(clone,rangeValues,2); else records = chopByChar(clone,',',rangeValues,2); if (records == 2) { trimSpaces(rangeValues[0]); trimSpaces(rangeValues[1]); wigDataConstraint[tableIndex][0] = sqlDouble(rangeValues[0]); wigDataConstraint[tableIndex][1] = sqlDouble(rangeValues[1]); if (wigDataConstraint[tableIndex][0] > wigDataConstraint[tableIndex][1]) { double d = wigDataConstraint[tableIndex][1]; wigDataConstraint[tableIndex][1] = wigDataConstraint[tableIndex][0]; wigDataConstraint[tableIndex][0] = d; } wiggleCompare[tableIndex] = wigInRange; } freeMem(clone); if (wigDataConstraint[tableIndex][1] == wigDataConstraint[tableIndex][0]) errAbort("For \"in range\" constraint, you must give two numbers separated by whitespace or comma."); } else { wigDataConstraint[tableIndex][0] = sqlDouble(pat); if (sameWord(cmp,"<")) wiggleCompare[tableIndex] = wigLessThan; else if (sameWord(cmp,"<=")) wiggleCompare[tableIndex] = wigLessEqual; else if (sameWord(cmp,"=")) wiggleCompare[tableIndex] = wigEqual; else if (sameWord(cmp,"!=")) wiggleCompare[tableIndex] = wigNotEqual; else if (sameWord(cmp,">=")) wiggleCompare[tableIndex]=wigGreaterEqual; else if (sameWord(cmp,">")) wiggleCompare[tableIndex] = wigGreaterThan; } } } static void wigPrintRow(struct wiggleStats *wigStats) { printf(" %s \n", wigStats->chrom); printf("\t %u \n", wigStats->chromStart+1); /* display closed coords */ printf("\t %u \n", wigStats->chromEnd); printf("\t %u \n", wigStats->count); printf("\t %d \n", wigStats->span); printf("\t %u \n", wigStats->count*wigStats->span); printf("\t %g \n", wigStats->lowerLimit); printf("\t %g \n", wigStats->lowerLimit+wigStats->dataRange); printf("\t %g \n", wigStats->dataRange); printf("\t %g \n", wigStats->mean); printf("\t %g \n", wigStats->variance); printf("\t %g \n", wigStats->stddev); printf("\n"); } static void wigPrintStats(struct wiggleStats **wsList, char *chrom) { struct wiggleStats *wigStats = (struct wiggleStats *)NULL; for (wigStats = *wsList; wigStats; wigStats = wigStats->next) { if (sameWord(wigStats->chrom,chrom)) wigPrintRow(wigStats); } } /* Check to see if this stats are done for this chrom */ static boolean wigStatsDone(int tableId, char *chrom) { if (chromsDone[tableId] == (struct hash *)NULL) return FALSE; else if (hashLookup(chromsDone[tableId],chrom)) return TRUE; else return FALSE; } static void wigMarkDone(int tableId, char *chrom) { if ((struct hash *)NULL == chromsDone[tableId]) chromsDone[tableId] = newHash(0); if ( (struct hashEl *)NULL == hashLookup(chromsDone[tableId],chrom)) hashAdd(chromsDone[tableId],chrom,NULL); } void wigMakeBedList(char *database, char *table, char *chrom, char *constraints, int tableId) { char *setting = cartCgiUsualString(cart, "tbWigCount", ctWigCountMenu[1]); unsigned maxLinesOut = MAX_LINES_OUT; if (setting != (char *) NULL) maxLinesOut = sqlUnsigned(setting); if ( ! wigStatsDone(tableId, chrom)) { wigData[tableId] = wigFetchData(database, table, chrom, winStart, winEnd, WIG_ALL_DATA, WIG_DATA_NOT_RETURNED, tableId, wiggleCompare[tableId], constraints, &bedListWig[tableId], maxLinesOut, &wigStatsList[tableId]); wigMarkDone(tableId, chrom); } } void wigDoStats(char *database, char *table, struct slName *chromList, int tableId, char *constraints) { struct slName *chromPtr; char *db = getTableDb(); struct sqlConnection *conn = hAllocOrConnect(db); struct sqlResult *sr = (struct sqlResult *)NULL; char query[256]; char **row = (char **)NULL; char wigFullTableName[256]; char *setting = cartCgiUsualString(cart, "tbWigCount", ctWigCountMenu[1]); unsigned maxLinesOut = MAX_LINES_OUT; int numChroms = 0; int tableRowsDisplayed = 0; if (setting != (char *) NULL) maxLinesOut = sqlUnsigned(setting); if (tableIsSplit) { getFullTableName(wigFullTableName, hDefaultChromDb(db), table); snprintf(query, sizeof(query), "show table status like '%s'", wigFullTableName); } else snprintf(query, sizeof(query), "show table status like '%s'", table); sr = sqlMustGetResult(conn,query); row = sqlNextRow(sr); // For some reason BORDER=1 does not work in our web.c nested table scheme. // So use web.c's trick of using an enclosing table to provide a border. puts("

" "\n" "
"); puts(""); if (row != NULL) { printf("\n", database, table, row[11]); } else { printf("\n", database, table); } sqlFreeResult(&sr); hFreeOrDisconnect(&conn); printf(""); printf(""); printf(""); printf(""); printf(""); printf("\n"); numChroms = slCount(chromList); for (chromPtr=chromList; chromPtr != NULL; chromPtr=chromPtr->next) { char *chrom = chromPtr->name; char wigFullTableName[256]; getFullTableName(wigFullTableName, chrom, table); if ( ! wigStatsDone(tableId, chrom)) { boolean dataFetchType = WIG_SUMMARY_ONLY; if (numChroms == 1) dataFetchType = WIG_ALL_DATA; if (wiggleCompare[tableId]) dataFetchType = WIG_ALL_DATA; if (numChroms > 1) wigData[tableId] = wigFetchData(database, wigFullTableName, chrom, winStart, winEnd, dataFetchType, WIG_DATA_NOT_RETURNED, tableId, wiggleCompare[tableId], constraints, (struct bed **)NULL, maxLinesOut, &wigStatsList[tableId]); else wigData[tableId] = wigFetchData(database, wigFullTableName, chrom, winStart, winEnd, dataFetchType, WIG_DATA_NOT_RETURNED, tableId, wiggleCompare[tableId], constraints, (struct bed **)NULL, 0, &wigStatsList[tableId]); wigMarkDone(tableId, chrom); } if (wigStatsDone(tableId, chrom)) { wigPrintStats(&wigStatsList[tableId], chrom); if (wigStatsList[tableId] != (struct wiggleStats *) NULL) ++tableRowsDisplayed; } else { printf("", chrom); printf("\n"); ++tableRowsDisplayed; } } /* No rows in table, indicate this no result */ if (!tableRowsDisplayed) puts(""); printf("
\n"); printf("" "
Database: %s Table: %s Last update: %s
Database: %s Table: %s
Chrom Data
start
Data
end
# of Data
values
Data
span
Bases
covered
Minimum Maximum Range Mean Variance Standard
deviation
%s No data
No data found matching this request
\n"); puts("

"); } /* void wigDoStats() */ void doWiggleCtOptions(boolean doCt) { struct hTableInfo *hti = getOutputHti(); char *table = getTableName(); char *table2 = getTable2Name(); char *op = cgiOptionalString("tbIntersectOp"); char *db = getTableDb(); char *outputType = cgiUsualString("outputType", cgiString("phase")); char *phase = (existsAndEqual("phase", getOutputPhase) ? cgiString("outputType") : cgiString("phase")); char *setting = NULL; char buf[256]; char *constraints = constrainFields(NULL); saveOutputOptionsState(); saveIntersectOptionsState(); webStart(cart, "Table Browser: %s %s: %s", hOrganism(database), freezeName, phase); checkTableExists(fullTableName); printf("
\n", hgTextName(), httpFormMethod); cartSaveSession(cart); cgiMakeHiddenVar("db", db); cgiMakeHiddenVar("table", getTableVar()); displayPosition(); cgiMakeHiddenVar("outputType", outputType); preserveConstraints(fullTableName, db, NULL); preserveTable2(); printf("

Select %s Options for %s:

\n", (doCt ? "Custom Track" : "DATA"), hti->rootName); puts("" "Help

"); puts("
"); if (doCt) { puts("" "" "Custom track header: "); } else { cgiMakeCheckBox("tbDoCustomTrack", cartCgiUsualBoolean(cart, "tbDoCustomTrack", FALSE)); puts(" Include " "" "custom track header: "); } puts("
name="); if (op == NULL) table2 = NULL; snprintf(buf, sizeof(buf), "tb_%s", hti->rootName); setting = cgiUsualString("tbCtName", buf); cgiMakeTextVar("tbCtName", setting, 16); puts("
description="); snprintf(buf, sizeof(buf), "table browser query on %s%s%s", table, (table2 ? ", " : ""), (table2 ? table2 : "")); setting = cgiUsualString("tbCtDesc", buf); cgiMakeTextVar("tbCtDesc", setting, 50); puts("
visibility="); setting = cartCgiUsualString(cart, "tbCtVis", ctWigVisMenu[2]); cgiMakeDropList("tbCtVis", ctWigVisMenu, ctWigVisMenuSize, setting); puts("
"); showConstraints(constraints, WIG_TABLE_1, TRUE); printf("

Select type of data output:
\n"); if (doCt) setting = cartCgiUsualString(cart, "tbWigDataType", "bedData"); else setting = cartCgiUsualString(cart, "tbWigDataType", "wigData"); cgiMakeRadioButton("tbWigDataType", "bedData", sameString(setting, "bedData")); printf("BED format (no data value information, only position)
\n"); cgiMakeRadioButton("tbWigDataType", "wigData", sameString(setting, "wigData")); printf("DATA VALUE format (position and real valued data)

\n"); puts("

Limit output to: "); setting = cartCgiUsualString(cart, "tbWigCount", ctWigCountMenu[1]); cgiMakeDropList("tbWigCount", ctWigCountMenu, ctWigCountMenuSize, setting); puts(" lines of data (to avoid browser overload)

\n"); if (doCt) { cartSetBoolean(cart, "tbDoCustomTrack", TRUE); cgiMakeButton("phase", getCtWiggleTrackPhase); cgiMakeButton("phase", getCtWiggleFilePhase); } else { cgiMakeButton("phase", getWigglePhase); } puts("
"); webEnd(); } /* void doWiggleCtOptions(boolean doCt) */ static void fileConstraints(char *constraints, int tableId, FILE *f) { if (constraints) fprintf(f, "#\tSQL query constraint: %s\n", constraints); if (wigConstraint[tableId]) { if (sameWord(wigConstraint[tableId],"in range")) fprintf(f,"#\tdata value constraint range: %s [%g , %g]\n", wigConstraint[tableId], wigDataConstraint[tableId][0], wigDataConstraint[tableId][1]); else fprintf(f,"#\tdata value constraint: %s %g\n", wigConstraint[tableId], wigDataConstraint[tableId][0]); } } void doGetWiggleData(boolean doCt) /* Find wiggle data and display it */ { struct slName *chromList, *chromPtr; char *db = getTableDb(); char *table = getTableName(); struct wiggleData *wigData = (struct wiggleData *) NULL; struct wiggleData *wdPtr = (struct wiggleData *) NULL; struct trackDb *tdb = (struct trackDb *)NULL; char *track = getTrackName(); unsigned linesOutput = 0; boolean doCtHdr = (cartCgiUsualBoolean(cart, "tbDoCustomTrack", FALSE) || doCt); char *constraints; char *setting = cartCgiUsualString(cart, "tbWigCount", ctWigCountMenu[1]); unsigned maxLinesOut = MAX_LINES_OUT; char *longLabel = cloneString("User Supplied Track"); char *ctDesc = cgiUsualString("tbCtDesc", table); char *ctName = cgiUsualString("tbCtName", table); char *ctVis = cgiUsualString("tbCtVis", "hide"); char *ctUrl = cgiUsualString("tbCtUrl", ""); struct customTrack *ctNew = NULL; char tableName[128]; char *visibility; int visNum = 0; boolean wigBED = FALSE; struct bed *bedList = NULL; FILE *wigAsciiFH = (FILE *) NULL; if (! sameString(customTrackPseudoDb, db)) { struct sqlConnection *conn = hAllocOrConnect(db); tdb = hMaybeTrackInfo(conn, track); hFreeOrDisconnect(&conn); } if (setting != (char *) NULL) maxLinesOut = sqlUnsigned(setting); setting = cartCgiUsualString(cart, "tbWigDataType", "wigData"); if ( sameString(setting, "bedData") ) wigBED = TRUE; saveOutputOptionsState(); saveIntersectOptionsState(); constraints = constrainFields(NULL); if ((constraints != NULL) && (constraints[0] == 0)) constraints = NULL; if (!doCt) { printf("Content-Type: text/plain\n\n"); webStartText(); } if (differentWord(ctName,table) ) snprintf(tableName, sizeof(tableName), "%s", ctName); else snprintf(tableName, sizeof(tableName), "tb_%s", table); if (ctDesc != (char *)NULL) { freeMem(longLabel); longLabel = cloneString(ctDesc); } if (ctVis != (char *)NULL) visibility = cloneString(ctVis); else visibility = cloneString("hide"); visNum = (int) hTvFromStringNoAbort(visibility); if (visNum < 0) visNum = 0; if (allGenome) chromList = getOrderedChromList(); else chromList = newSlName(chrom); if (doCtHdr && wigBED && !doCt) { printf("track name=\"%s\" description=\"%s\" " "visibility=%s\n", tableName, longLabel, visibility); showConstraints(constraints, WIG_TABLE_1, FALSE); } if (doCt) { int fields=0; if (wigBED) fields=4; ctNew = newCT(tableName, longLabel, visNum, ctUrl, fields); if (wigBED) ctNew->wiggle = FALSE; else { struct tempName tn; makeTempName(&tn, "hgtct", ".wig"); ctNew->wigFile = cloneString(tn.forCgi); makeTempName(&tn, "hgtct", ".wib"); ctNew->wibFile = cloneString(tn.forCgi); makeTempName(&tn, "hgtct", ".wia"); ctNew->wigAscii = cloneString(tn.forCgi); wigAsciiFH = mustOpen(ctNew->wigAscii, "w"); #if defined(DEBUG) /* dbg */ /* allow file readability for debug */ chmod(ctNew->wigAscii, 0666); #endif ctNew->wiggle = TRUE; } } for (chromPtr=chromList; chromPtr != NULL && (linesOutput < maxLinesOut); chromPtr=chromPtr->next) { char *chrom = chromPtr->name; char wigFullTableName[256]; int bedLength = 0; getFullTableName(wigFullTableName, chrom, table); if (wigBED) { wigData = wigFetchData(database, table, chrom, winStart, winEnd, WIG_ALL_DATA, WIG_DATA_NOT_RETURNED, WIG_TABLE_1, wiggleCompare[WIG_TABLE_1], constraints, &bedListWig[WIG_TABLE_1], maxLinesOut, (struct wiggleStats **)NULL); wigMarkDone(WIG_TABLE_1, chrom); bedLength = slCount(bedListWig[WIG_TABLE_1]); } else { wigData = wigFetchData(database, table, chrom, winStart, winEnd, WIG_ALL_DATA, WIG_RETURN_DATA, WIG_TABLE_1, wiggleCompare[WIG_TABLE_1], constraints, (struct bed **)NULL, maxLinesOut, (struct wiggleStats **)NULL); wigMarkDone(WIG_TABLE_1, chrom); } if (wigData) { unsigned span = 0; char *chrom = (char *) NULL; unsigned char colorR, colorG, colorB; unsigned char altColorR, altColorG, altColorB; float priority; int wordCount; char *words[128]; char *trackType = (char *) NULL; boolean nextSpan = FALSE; if (tdb && tdb->type) { char *typeLine = cloneString(tdb->type); if (ctDesc == (char *)NULL) { freeMem(longLabel); longLabel = cloneString(tdb->longLabel); } priority = tdb->priority; wordCount = chopLine(typeLine,words); if (wordCount > 0) trackType = words[0]; colorR = tdb->colorR; colorG = tdb->colorG; colorB = tdb->colorB; altColorR = tdb->altColorR; altColorG = tdb->altColorG; altColorB = tdb->altColorB; colorR = colorG = colorB = 0; altColorR = altColorG = altColorB = 128; } else { priority = 42; if (ctDesc == (char *)NULL) { freeMem(longLabel); longLabel = cloneString("User Supplied Track"); } colorR = colorG = colorB = 255; altColorR = altColorG = altColorB = 128; } if (doCt) { ctNew->tdb->longLabel = longLabel; } if (doCtHdr && (!wigBED)) { if (doCt) { struct dyString *wigSettings = newDyString(0); ctNew->tdb->priority = priority; ctNew->tdb->colorR = colorR; ctNew->tdb->colorG = colorB; ctNew->tdb->colorB = colorB; ctNew->tdb->altColorR = altColorR; ctNew->tdb->altColorG = altColorB; ctNew->tdb->altColorB = altColorB; /* more settings to be done */ dyStringPrintf(wigSettings, "type='wiggle_0'\twigFile='%s'\twibFile='%s'", ctNew->wigFile, ctNew->wibFile); ctNew->tdb->settings = dyStringCannibalize(&wigSettings); fileConstraints(constraints, WIG_TABLE_1, wigAsciiFH); } else { printf("track type=wiggle_0 name=%s description=\"%s\" " "visibility=%s color=%d,%d,%d altColor=%d,%d,%d " "priority=%g\n", tableName, longLabel, visibility, colorR, colorG, colorB, altColorR, altColorG, altColorB, priority); showConstraints(constraints, WIG_TABLE_1, FALSE); } } for (wdPtr = wigData; (linesOutput < maxLinesOut) && (wdPtr != (struct wiggleData *) NULL); wdPtr= wdPtr->next) { if ((chrom == (char *) NULL) || differentWord(chrom,wdPtr->chrom)) { if (!(doCtHdr | wigBED)) { if (!doCt) printf("#\t"); } if (!wigBED) { if (doCt) fprintf(wigAsciiFH, "variableStep chrom=%s span=%u\n", wdPtr->chrom, wdPtr->span); else printf("variableStep chrom=%s span=%u\n", wdPtr->chrom, wdPtr->span); } chrom = wdPtr->chrom; span = wdPtr->span; } if (span != wdPtr->span) { if (!(doCtHdr | wigBED)) printf("#\t"); if (!wigBED) { if (doCt) fprintf(wigAsciiFH, "variableStep chrom=%s span=%u\n", wdPtr->chrom, wdPtr->span); else printf("variableStep chrom=%s span=%u\n", wdPtr->chrom, wdPtr->span); } span = wdPtr->span; } if (wdPtr->data) { struct wiggleDatum *wd = wdPtr->data; int i; for (i = 0; (!nextSpan) && (linesOutput < maxLinesOut) && (i < wdPtr->count); ++i, ++wd) { if (doCt) fprintf(wigAsciiFH, "%u\t%g\n", wd->chromStart+1, wd->value); else printf("%u\t%g\n", wd->chromStart+1, wd->value); ++linesOutput; } } else if (bedLength > 0) { struct bed *bedEl = bedListWig[WIG_TABLE_1]; for ( ; linesOutput < maxLinesOut && bedEl; bedEl = bedEl->next) { if (doCt) { struct bed *newBed = cloneBed(bedEl); slAddHead(&bedList, newBed); } else printBedEl(bedEl); ++linesOutput; } if (doCt) bedFreeList(&bedListWig[WIG_TABLE_1]); bedLength = 0; } } wigFreeData(&wigData); } } if ((ctNew != NULL) && (bedList != NULL)) { slReverse(&bedList); ctNew->bedList = bedList; } if ((ctNew != NULL) && ((ctNew->bedList != NULL) || (ctNew->wigAscii != NULL))) { /* Load existing custom tracks and add this new one: */ struct customTrack *ctList = getCustomTracks(); slAddHead(&ctList, ctNew); carefulClose(&wigAsciiFH); /* Save the custom tracks out to file (overwrite the old file): */ customTracksSaveCart(cart, ctList); } if (doCt) { char browserUrl[128]; char headerText[256]; int redirDelay = 5; if (linesOutput < 1) { printf("Content-Type: text/plain\n\n"); webStartText(); printf("#\tno results returned from query\n"); webEnd(); } else { safef(browserUrl, sizeof(browserUrl), "%s?db=%s&position=%s:%d-%d", hgTracksName(), database, chrom, winStart, winEnd); safef(headerText, sizeof(headerText), "", redirDelay, browserUrl); webStartHeader(cart, headerText, "Table Browser: %s %s: %s", hOrganism(database), freezeName, getCtPhase); printf("You will be automatically redirected to the genome browser in\n" "%d seconds, or you can
\n" "click here to continue.\n", redirDelay, browserUrl); webEnd(); } } else { if (linesOutput < 1) { printf("#\tno results returned from query\n"); } else if (linesOutput >= maxLinesOut) printf("#\tmaximum data output of %u lines reached\n", maxLinesOut); webEnd(); } } /* void doGetWiggleData(boolean doCt) */