4898794edd81be5285ea6e544acbedeaeb31bf78
max
  Tue Nov 23 08:10:57 2021 -0800
Fixing pointers to README file for license in all source code files. refs #27614

diff --git src/hg/hgText/hgWigText.c src/hg/hgText/hgWigText.c
index aebb4f6..36883ba 100644
--- src/hg/hgText/hgWigText.c
+++ src/hg/hgText/hgWigText.c
@@ -1,885 +1,885 @@
 /*	hgWigText.c - functions for wiggle tracks in hgText	*/
 
 /* Copyright (C) 2013 The Regents of the University of California 
- * See README in this or parent directory for licensing information. */
+ * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */
 
 #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("<P>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("</P>\n");
     else
 	printf("NONE</P>\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("<TR><TH ALIGN=LEFT> %s </TH>\n", wigStats->chrom);
 printf("\t<TD ALIGN=RIGHT> %u </TD>\n", wigStats->chromStart+1);
 					/* display closed coords */
 printf("\t<TD ALIGN=RIGHT> %u </TD>\n", wigStats->chromEnd);
 printf("\t<TD ALIGN=RIGHT> %u </TD>\n", wigStats->count);
 printf("\t<TD ALIGN=RIGHT> %d </TD>\n", wigStats->span);
 printf("\t<TD ALIGN=RIGHT> %u </TD>\n", wigStats->count*wigStats->span);
 printf("\t<TD ALIGN=RIGHT> %g </TD>\n", wigStats->lowerLimit);
 printf("\t<TD ALIGN=RIGHT> %g </TD>\n", wigStats->lowerLimit+wigStats->dataRange);
 printf("\t<TD ALIGN=RIGHT> %g </TD>\n", wigStats->dataRange);
 printf("\t<TD ALIGN=RIGHT> %g </TD>\n", wigStats->mean);
 printf("\t<TD ALIGN=RIGHT> %g </TD>\n", wigStats->variance);
 printf("\t<TD ALIGN=RIGHT> %g </TD>\n", wigStats->stddev);
 printf("<TR>\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);
     sqlSafef(query, sizeof(query), "show table status like '%s'", wigFullTableName);
     }
 else
     sqlSafef(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("<P><!--outer table is for border purposes-->" "\n"
      "<TABLE BGCOLOR='#" HG_COL_BORDER "' BORDER=0 CELLSPACING=0 CELLPADDING=1><TR><TD>");
 
 puts("<TABLE BGCOLOR='#" HG_COL_INSIDE "' BORDER=1 CELLSPACING=0>");
 
 if (row != NULL)
     {
     printf("<TR><TD COLSPAN=12>\n");
     printf("<TABLE COLS=12 ALIGN=CENTER HSPACE=0>"
 	"<TR><TH COLSPAN=1 ALIGN=LEFT> Database: %s </TH><TH COLSPAN=1 ALIGN=CENTER> Table: %s </TH><TH COLSPAN=10 ALIGN=RIGHT>  Last update: %s </TH></TR></TABLE></TD></TR>\n",
 	database, table, row[11]);
     }
 else
     {
     printf("<TR><TH COLSPAN=6 ALIGN=LEFT> Database: %s </TH><TH COLSPAN=6 ALIGN=RIGHT> Table: %s </TH></TR>\n", database,
 	table);
     }
 
 sqlFreeResult(&sr);
 hFreeOrDisconnect(&conn);
 
 printf("<TR><TH> Chrom </TH><TH> Data <BR> start </TH>");
 printf("<TH> Data <BR> end </TH>");
 printf("<TH> # of Data <BR> values </TH><TH> Data <BR> span </TH>");
 printf("<TH> Bases <BR> covered </TH><TH> Minimum </TH>");
 printf("<TH> Maximum </TH><TH> Range </TH><TH> Mean </TH>");
 printf("<TH> Variance </TH><TH> Standard <BR> deviation </TH></TR>\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("<TR><TH ALIGN=LEFT> %s </TH>", chrom);
 	printf("<TH COLSPAN=11> No data </TH></TR>\n");
 	++tableRowsDisplayed;
 	}
     }
 
 /*	No rows in table, indicate this no result */
 if (!tableRowsDisplayed)
     puts("<TR><TH ALIGN=CENTER COLSPAN=12> No data found matching this request </TH></TR>");
 
 printf("</TABLE>\n");
 puts("</TD></TR></TABLE></P>");
 }	/*	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("<FORM ACTION=\"%s\" NAME=\"mainForm\" METHOD=\"%s\">\n",
        hgTextName(), httpFormMethod);
 cartSaveSession(cart);
 cgiMakeHiddenVar("db", db);
 
 cgiMakeHiddenVar("table", getTableVar());
 displayPosition();
 cgiMakeHiddenVar("outputType", outputType);
 preserveConstraints(fullTableName, db, NULL);
 preserveTable2();
 printf("<H3> Select %s Options for %s: </H3>\n",
        (doCt ? "Custom Track" : "DATA"), hti->rootName);
 puts("<A HREF=\"/goldenPath/help/hgTextHelp.html#BEDOptions\">"
      "<B>Help</B></A><P>");
 puts("<TABLE><TR><TD>");
 if (doCt)
     {
     puts("</TD><TD>"
 	 "<A HREF=\"/goldenPath/help/customTrack.html\" TARGET=_blank>"
 	 "Custom track</A> header: </B>");
     }
 else
     {
     cgiMakeCheckBox("tbDoCustomTrack",
 		    cartCgiUsualBoolean(cart, "tbDoCustomTrack", FALSE));
     puts("</TD><TD> <B> Include "
 	 "<A HREF=\"/goldenPath/help/customTrack.html\" TARGET=_blank>"
 	 "custom track</A> header: </B>");
     }
 puts("</TD></TR><TR><TD></TD><TD>name=");
 if (op == NULL)
     table2 = NULL;
 snprintf(buf, sizeof(buf), "tb_%s", hti->rootName);
 setting = cgiUsualString("tbCtName", buf);
 cgiMakeTextVar("tbCtName", setting, 16);
 puts("</TD></TR><TR><TD></TD><TD>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("</TD></TR><TR><TD></TD><TD>visibility=");
 setting = cartCgiUsualString(cart, "tbCtVis", ctWigVisMenu[2]);
 cgiMakeDropList("tbCtVis", ctWigVisMenu, ctWigVisMenuSize, setting);
 puts("</TD></TR><TR><TD></TD></TR></TABLE>");
 
 showConstraints(constraints, WIG_TABLE_1, TRUE);
 
 printf("<P> <B> Select type of data output: </B> <BR>\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)<BR>\n");
 cgiMakeRadioButton("tbWigDataType", "wigData", sameString(setting, "wigData"));
 printf("DATA VALUE format (position and real valued data)</P>\n");
 
 puts("<P> <B> Limit output to: </B>");
 setting = cartCgiUsualString(cart, "tbWigCount", ctWigCountMenu[1]);
 cgiMakeDropList("tbWigCount", ctWigCountMenu, ctWigCountMenuSize, setting);
 puts("<B> lines of data </B> (to avoid browser overload)</P>\n");
 
 if (doCt)
     {
     cartSetBoolean(cart, "tbDoCustomTrack", TRUE);
     cgiMakeButton("phase", getCtWiggleTrackPhase);
     cgiMakeButton("phase", getCtWiggleFilePhase);
     }
 else
     {
     cgiMakeButton("phase", getWigglePhase);
     }
 puts("</FORM>");
 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),
 	      "<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"%d;URL=%s\">",
 	      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 <BR>\n"
 	       "<A HREF=\"%s\">click here to continue</A>.\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)	*/