struct wiggleDataStream *wigChromRawStats(char *chrom) /* Fetch stats for wig data in chrom. * Returns a wiggleDataStream, free it with wiggleDataStreamFree() */ { char splitTableOrFileName[256]; struct customTrack *ct = NULL; boolean isCustom = FALSE; struct wiggleDataStream *wds = NULL; int operations = wigFetchRawStats; char *table = curTable; /* ct, isCustom, wds are set here */ if (isCustomTrack(table)) { ct = lookupCt(table); isCustom = TRUE; if (! ct->wiggle) errAbort("called to work on a custom track '%s' that isn't wiggle data ?", table); if (ct->dbTrack) safef(splitTableOrFileName,ArraySize(splitTableOrFileName), "%s", ct->dbTableName); else safef(splitTableOrFileName,ArraySize(splitTableOrFileName), "%s", ct->wigFile); } wds = wiggleDataStreamNew(); wds->setChromConstraint(wds, chrom); if (isCustom) { if (ct->dbTrack) wds->getData(wds, CUSTOM_TRASH, splitTableOrFileName, operations); else wds->getData(wds, NULL, splitTableOrFileName, operations); } else { boolean hasBin = FALSE; if (hFindSplitTable(database, chrom, table, splitTableOrFileName, &hasBin)) { wds->getData(wds, database, splitTableOrFileName, operations); } } return wds; }
boolean doGetBedOrCt(struct sqlConnection *conn, boolean doCt, boolean doCtFile, boolean redirectToGb) /* Actually output bed or custom track. Return TRUE unless no results. */ { char *db = cloneString(database); char *table = curTable; struct hTableInfo *hti = getHti(db, table, conn); struct featureBits *fbList = NULL, *fbPtr; struct customTrack *ctNew = NULL; boolean doCtHdr = (cartUsualBoolean(cart, hgtaPrintCustomTrackHeaders, FALSE) || doCt || doCtFile); char *ctWigOutType = cartCgiUsualString(cart, hgtaCtWigOutType, outWigData); char *fbQual = fbOptionsToQualifier(); char fbTQ[128]; int fields = hTableInfoBedFieldCount(hti); boolean gotResults = FALSE; struct region *region, *regionList = getRegions(); boolean isBedGr = isBedGraph(curTable); boolean isBgWg = isBigWigTable(curTable); boolean needSubtrackMerge = anySubtrackMerge(database, curTable); boolean doDataPoints = FALSE; boolean isWig = isWiggle(database, table); struct wigAsciiData *wigDataList = NULL; struct dataVector *dataVectorList = NULL; boolean doRgb = bedItemRgb(hTrackDbForTrack(db, curTable)); if (!cartUsualBoolean(cart, hgtaDoGreatOutput, FALSE) && !doCt) { textOpen(); } if (cartUsualBoolean(cart, hgtaDoGreatOutput, FALSE)) fputs("#", stdout); if ((isWig || isBedGr || isBgWg) && sameString(outWigData, ctWigOutType)) doDataPoints = TRUE; for (region = regionList; region != NULL; region = region->next) { struct bed *bedList = NULL, *bed; struct lm *lm = lmInit(64*1024); struct dataVector *dv = NULL; if (isWig && doDataPoints) { if (needSubtrackMerge) { dv = wiggleDataVector(curTrack, curTable, conn, region); if (dv != NULL) slAddHead(&dataVectorList, dv); } else { int count = 0; struct wigAsciiData *wigData = NULL; struct wigAsciiData *asciiData; struct wigAsciiData *next; wigData = getWiggleAsData(conn, curTable, region); for (asciiData = wigData; asciiData; asciiData = next) { next = asciiData->next; if (asciiData->count) { slAddHead(&wigDataList, asciiData); ++count; } } slReverse(&wigDataList); } } else if (isBedGr && doDataPoints) { dv = bedGraphDataVector(curTable, conn, region); if (dv != NULL) slAddHead(&dataVectorList, dv); } else if (isBgWg && doDataPoints) { dv = bigWigDataVector(curTable, conn, region); if (dv != NULL) slAddHead(&dataVectorList, dv); } else if (isWig || isBgWg) { dv = wiggleDataVector(curTrack, curTable, conn, region); bedList = dataVectorToBedList(dv); dataVectorFree(&dv); } else if (isBedGr) { bedList = getBedGraphAsBed(conn, curTable, region); } else { bedList = cookedBedList(conn, curTable, region, lm, &fields); } /* this is a one-time only initial creation of the custom track * structure to receive the results. gotResults turns it off after * the first time. */ if (doCtHdr && !gotResults && ((bedList != NULL) || (wigDataList != NULL) || (dataVectorList != NULL))) { ctNew = beginCustomTrack(table, fields, doCt, (isWig || isBedGr || isBgWg), doDataPoints); } if (doDataPoints && (wigDataList || dataVectorList)) gotResults = TRUE; else { if ((fbQual == NULL) || (fbQual[0] == 0)) { for (bed = bedList; bed != NULL; bed = bed->next) { if (bed->name != NULL) { subChar(bed->name, ' ', '_'); } if (doCt) { struct bed *dupe = cloneBed(bed); /* Out of local memory. */ slAddHead(&ctNew->bedList, dupe); } else { if (doRgb) bedTabOutNitemRgb(bed, fields, stdout); else bedTabOutN(bed, fields, stdout); } gotResults = TRUE; } } else { safef(fbTQ, sizeof(fbTQ), "%s:%s", hti->rootName, fbQual); fbList = fbFromBed(db, fbTQ, hti, bedList, 0, 0, FALSE, FALSE); if (fields >= 6) fields = 6; else if (fields >= 4) fields = 4; else fields = 3; if (doCt && ctNew) { ctNew->fieldCount = fields; safef(ctNew->tdb->type, strlen(ctNew->tdb->type)+1, "bed %d", fields); } for (fbPtr=fbList; fbPtr != NULL; fbPtr=fbPtr->next) { if (fbPtr->name != NULL) { char *ptr = strchr(fbPtr->name, ' '); if (ptr != NULL) *ptr = 0; } if (doCt) { struct bed *fbBed = fbToBedOne(fbPtr); slAddHead(&ctNew->bedList, fbBed ); } else { if (fields >= 6) hPrintf("%s\t%d\t%d\t%s\t%d\t%c\n", fbPtr->chrom, fbPtr->start, fbPtr->end, fbPtr->name, 0, fbPtr->strand); else if (fields >= 4) hPrintf("%s\t%d\t%d\t%s\n", fbPtr->chrom, fbPtr->start, fbPtr->end, fbPtr->name); else hPrintf("%s\t%d\t%d\n", fbPtr->chrom, fbPtr->start, fbPtr->end); } gotResults = TRUE; } featureBitsFreeList(&fbList); } } bedList = NULL; lmCleanup(&lm); } if (!gotResults) { hPrintf(NO_RESULTS); } else if (doCt) { int wigDataSize = 0; /* Load existing custom tracks and add this new one: */ struct customTrack *ctList = getCustomTracks(); removeNamedCustom(&ctList, ctNew->tdb->table); if (doDataPoints) { if (needSubtrackMerge || isBedGr || isBgWg) { slReverse(&dataVectorList); wigDataSize = dataVectorWriteWigAscii(dataVectorList, ctNew->wigAscii, 0, NULL); // TODO: see if can make prettier wig output here that // doesn't necessarily have one value per base } else { struct wiggleDataStream *wds = NULL; /* create an otherwise empty wds so we can print out the list */ wds = wiggleDataStreamNew(); wds->ascii = wigDataList; wigDataSize = wds->asciiOut(wds, db, ctNew->wigAscii, TRUE, FALSE); #if defined(DEBUG) /* dbg */ /* allow file readability for debug */ chmod(ctNew->wigAscii, 0666); #endif wiggleDataStreamFree(&wds); } } else slReverse(&ctNew->bedList); slAddHead(&ctList, ctNew); /* Save the custom tracks out to file (overwrite the old file): */ customTracksSaveCart(db, cart, ctList); /* Put up redirect-to-browser page. */ if (redirectToGb) { char browserUrl[256]; char headerText[512]; int redirDelay = 3; safef(browserUrl, sizeof(browserUrl), "%s?%s&db=%s", hgTracksName(), cartSidUrlString(cart), database); safef(headerText, sizeof(headerText), "<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"%d;URL=%s\">", redirDelay, browserUrl); webStartHeader(cart, database, headerText, "Table Browser: %s %s: %s", hOrganism(database), freezeName, "get custom track"); if (doDataPoints) { hPrintf("There are %d data points in custom track. ", wigDataSize); } else { hPrintf("There are %d items in custom track. ", slCount(ctNew->bedList)); } hPrintf("You will be automatically redirected to the genome browser in\n" "%d seconds, or you can \n" "<A HREF=\"%s\">click here to continue</A>.\n", redirDelay, browserUrl); } } else if (doDataPoints) { if (needSubtrackMerge || isBedGr || isBgWg) { slReverse(&dataVectorList); dataVectorWriteWigAscii(dataVectorList, "stdout", 0, NULL); } else { /* create an otherwise empty wds so we can print out the list */ struct wiggleDataStream *wds = NULL; wds = wiggleDataStreamNew(); wds->ascii = wigDataList; wds->asciiOut(wds, db, "stdout", TRUE, FALSE); wiggleDataStreamFree(&wds); } } return gotResults; }
void genericWiggleClick(struct sqlConnection *conn, struct trackDb *tdb, char *item, int start) /* Display details for Wiggle data tracks. * conn may be NULL for custom tracks when from file */ { char *chrom = cartString(cart, "c"); char table[64]; boolean hasBin; unsigned span = 0; struct wiggleDataStream *wds = wiggleDataStreamNew(); unsigned long long valuesMatched = 0; struct histoResult *histoGramResult; float *valuesArray = NULL; size_t valueCount = 0; struct customTrack *ct = NULL; boolean isCustom = FALSE; int operations = wigFetchStats; /* default operation */ if (startsWith("ct_", tdb->table)) { ct = lookupCt(tdb->table); if (!ct) { warn("<P>wiggleClick: can not find custom wiggle track '%s'</P>", tdb->table); return; } if (! ct->wiggle) { warn("<P>wiggleClick: called to do stats on a custom track that isn't wiggle data ?</P>"); return; } if (ct->dbTrack) { safef(table,ArraySize(table), "%s", ct->dbTableName); span = minSpan(conn, table, chrom, winStart, winEnd, cart, tdb); } else { safef(table,ArraySize(table), "%s", ct->wigFile); span = 0; /* cause all spans to be examined */ } isCustom = TRUE; } else { hFindSplitTable(database, seqName, tdb->table, table, &hasBin); /*span = spanInUse(conn, table, chrom, winStart, winEnd, cart);*/ span = minSpan(conn, table, chrom, winStart, winEnd, cart, tdb); } /* if for some reason we don't have a chrom and win positions, this * should be run in a loop that does one chrom at a time. In the * case of hgc, there seems to be a chrom and a position. */ wds->setSpanConstraint(wds, span); wds->setChromConstraint(wds, chrom); wds->setPositionConstraint(wds, winStart, winEnd); /* If our window is less than some number of points, we can do * the histogram too. */ #define MAX_WINDOW_ALLOW_STATS 100000001 #define MAX_WINDOW_ALLOW_STRING "100,000,000" if ((winEnd - winStart) < MAX_WINDOW_ALLOW_STATS) operations |= wigFetchAscii; /* We want to also fetch the actual data values so we can run a * histogram function on them. You can't fetch the data in the * form of the data array since the span information is then lost. * We have to do the ascii data list format, and prepare that to * send to the histogram function. */ if (isCustom) { if (ct->dbTrack) valuesMatched = wds->getData(wds, CUSTOM_TRASH, table, operations); else valuesMatched = wds->getData(wds, (char *)NULL, table, operations); } else valuesMatched = wds->getData(wds, database, table, operations); statsPreamble(wds, chrom, winStart, winEnd, span, valuesMatched, NULL); /* output statistics table * (+sort, +html output, +with header, +close table) */ wds->statsOut(wds, database, "stdout", TRUE, TRUE, TRUE, FALSE); if ((winEnd - winStart) < MAX_WINDOW_ALLOW_STATS) { char *words[16]; int wordCount = 0; char *dupe = cloneString(tdb->type); double minY, maxY, tDbMinY, tDbMaxY; float hMin, hMax, hRange; wordCount = chopLine(dupe, words); wigFetchMinMaxY(tdb, &minY, &maxY, &tDbMinY, &tDbMaxY, wordCount, words); hMin = min(minY,tDbMinY); hMax = max(maxY,tDbMaxY); hRange = hMax - hMin; /* convert the ascii data listings to one giant float array */ valuesArray = wds->asciiToDataArray(wds, valuesMatched, &valueCount); /* let's see if we really want to use the range from the track type * line, or the actual range in this data. If there is a good * actual range in the data, use that instead */ if (hRange > 0.0) { if (wds->stats->dataRange != 0) hRange = 0.0; } /* If we have a valid range, use a specified 20 bin histogram * NOTE: pass 21 as binCount to get a 20 bin histogram */ if (hRange > 0.0) histoGramResult = histoGram(valuesArray, valueCount, (hRange/20.0), (unsigned) 21, hMin, hMin, hMax, (struct histoResult *)NULL); else histoGramResult = histoGram(valuesArray, valueCount, NAN, (unsigned) 0, NAN, (float) wds->stats->lowerLimit, (float) (wds->stats->lowerLimit + wds->stats->dataRange), (struct histoResult *)NULL); /* histoGram() may return NULL if it doesn't work, that's OK, the * print out will indicate no results (TRUE == html output) */ printHistoGram(histoGramResult, TRUE); freeHistoGram(&histoGramResult); freeMem(valuesArray); } else { printf("<P>(viewing windows of fewer than %s bases will also" " display a histogram)</P>\n", MAX_WINDOW_ALLOW_STRING); } wiggleDataStreamFree(&wds); }