0f8ec54de20313713243e8d359449f28cfb4514d hiram Tue Mar 19 14:22:48 2019 -0700 object data outputs refs #18869 diff --git src/hg/hubApi/getData.c src/hg/hubApi/getData.c index 38a8598..2c0e55b 100644 --- src/hg/hubApi/getData.c +++ src/hg/hubApi/getData.c @@ -1,35 +1,35 @@ /* manage endpoint /getData/ functions */ #include "dataApi.h" static void tableDataOutput(struct sqlConnection *conn, struct jsonWrite *jw, char *query, char *table) /* output the table data from the specified query string */ { char **columnNames = NULL; char **columnTypes = NULL; int columnCount = tableColumns(conn, jw, table, &columnNames, &columnTypes); -jsonWriteListStart(jw, "trackData"); +jsonWriteListStart(jw, table); struct sqlResult *sr = sqlGetResult(conn, query); char **row = NULL; while ((row = sqlNextRow(sr)) != NULL) { - jsonWriteListStart(jw, NULL); + jsonWriteObjectStart(jw, NULL); int i = 0; for (i = 0; i < columnCount; ++i) - jsonWriteString(jw, NULL, row[i]); - jsonWriteListEnd(jw); + jsonWriteString(jw, columnNames[i], row[i]); + jsonWriteObjectEnd(jw); } jsonWriteListEnd(jw); } static struct bbiFile *bigFileOpen(char *trackType, char *bigDataUrl) { struct bbiFile *bbi = NULL; if (startsWith("bigBed", trackType)) bbi = bigBedFileOpen(bigDataUrl); else if (startsWith("bigWig", trackType)) bbi = bigWigFileOpen(bigDataUrl); return bbi; } @@ -59,79 +59,80 @@ { struct sqlFieldType *ft, *list = NULL; struct asColumn *col; for (col = as->columnList; col != NULL; col = col->next) { struct dyString *type = asColumnToSqlType(col); ft = sqlFieldTypeNew(col->name, type->string); slAddHead(&list, ft); dyStringFree(&type); } slReverse(&list); return list; } static void bedDataOutput(struct jsonWrite *jw, struct bbiFile *bbi, - char *chrom, unsigned start, unsigned end, unsigned maxItems) + char *chrom, unsigned start, unsigned end, unsigned maxItems, + struct sqlFieldType *fiList) /* output bed data for one chrom in the given bbi file */ { struct lm *bbLm = lmInit(0); struct bigBedInterval *iv, *ivList = NULL; ivList = bigBedIntervalQuery(bbi,chrom, start, end, 0, bbLm); char *row[bbi->fieldCount]; for (iv = ivList; iv; iv = iv->next) { char startBuf[16], endBuf[16]; bigBedIntervalToRow(iv, chrom, startBuf, endBuf, row, bbi->fieldCount); - jsonWriteListStart(jw, NULL); + jsonWriteObjectStart(jw, NULL); int i; + struct sqlFieldType *fi = fiList; for (i = 0; i < bbi->fieldCount; ++i) { - jsonWriteString(jw, NULL, row[i]); + jsonWriteString(jw, fi->name, row[i]); + fi = fi->next; } - jsonWriteListEnd(jw); + jsonWriteObjectEnd(jw); } lmCleanup(&bbLm); } static void wigDataOutput(struct jsonWrite *jw, struct bbiFile *bwf, char *chrom, unsigned start, unsigned end, unsigned maxItems) /* output wig data for one chrom in the given bwf file */ { struct lm *lm = lmInit(0); struct bbiInterval *iv, *ivList = bigWigIntervalQuery(bwf, chrom, start, end, lm); if (NULL == ivList) return; unsigned itemCount = 0; -jsonWriteObjectStart(jw, NULL); jsonWriteListStart(jw, chrom); for (iv = ivList; iv && itemCount < maxItems; iv = iv->next) { - jsonWriteListStart(jw, NULL); + jsonWriteObjectStart(jw, NULL); int s = max(iv->start, start); int e = min(iv->end, end); double val = iv->val; - jsonWriteNumber(jw, NULL, (long long)s); - jsonWriteNumber(jw, NULL, (long long)e); - jsonWriteDouble(jw, NULL, val); - jsonWriteListEnd(jw); + jsonWriteNumber(jw, "start", (long long)s); + jsonWriteNumber(jw, "end", (long long)e); + jsonWriteDouble(jw, "value", val); + jsonWriteObjectEnd(jw); ++itemCount; } jsonWriteListEnd(jw); -jsonWriteObjectEnd(jw); } static void wigData(struct jsonWrite *jw, struct bbiFile *bwf, char *chrom, unsigned start, unsigned end, unsigned maxItems) /* output the data for a bigWig bbi file */ { struct bbiChromInfo *chromList = NULL; // struct bbiSummaryElement sum = bbiTotalSummary(bwf); if (isEmpty(chrom)) { chromList = bbiChromList(bwf); struct bbiChromInfo *bci; for (bci = chromList; bci; bci = bci->next) { wigDataOutput(jw, bwf, bci->name, 0, bci->size, maxItems); @@ -177,93 +178,95 @@ { if (sameWord(thisTrack->track, track)) break; } if (NULL == thisTrack) apiErrAbort("failed to find specified track=%s in genome=%s for endpoint '/getdata/track' given hubUrl='%s'", track, genome, hubUrl); char *bigDataUrl = trackDbSetting(thisTrack, "bigDataUrl"); struct bbiFile *bbi = bigFileOpen(thisTrack->type, bigDataUrl); if (NULL == bbi) apiErrAbort("track type %s management not implemented yet TBD track=%s in genome=%s for endpoint '/getdata/track' given hubUrl='%s'", track, genome, hubUrl); struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "hubUrl", hubUrl); jsonWriteString(jw, "genome", genome); -jsonWriteString(jw, "track", track); +// jsonWriteString(jw, "track", track); unsigned chromSize = 0; struct bbiChromInfo *chromList = NULL; if (isNotEmpty(chrom)) { - jsonWriteString(jw, "chrom", chrom); +// jsonWriteString(jw, "chrom", chrom); chromSize = bbiChromSize(bbi, chrom); if (0 == chromSize) apiErrAbort("can not find specified chrom=%s in bigBed file URL %s", chrom, bigDataUrl); jsonWriteNumber(jw, "chromSize", (long long)chromSize); } else { chromList = bbiChromList(bbi); jsonWriteNumber(jw, "chromCount", (long long)slCount(chromList)); } unsigned uStart = 0; unsigned uEnd = chromSize; if ( ! (isEmpty(start) || isEmpty(end)) ) { uStart = sqlUnsigned(start); uEnd = sqlUnsigned(end); jsonWriteNumber(jw, "start", uStart); jsonWriteNumber(jw, "end", uEnd); } jsonWriteString(jw, "bigDataUrl", bigDataUrl); jsonWriteString(jw, "trackType", thisTrack->type); if (startsWith("bigBed", thisTrack->type)) { struct asObject *as = bigBedAsOrDefault(bbi); - struct sqlFieldType *fi, *fiList = sqlFieldTypesFromAs(as); - jsonWriteListStart(jw, "columnNames"); + struct sqlFieldType *fiList = sqlFieldTypesFromAs(as); unsigned maxItems = 0; /* TBD will use this later for paging */ +#ifdef NOT + jsonWriteListStart(jw, "columnNames"); // int columnCount = slCount(fiList); for (fi = fiList; fi; fi = fi->next) { jsonWriteObjectStart(jw, NULL); jsonWriteString(jw, fi->name, fi->type); jsonWriteObjectEnd(jw); } jsonWriteListEnd(jw); - jsonWriteListStart(jw, "trackData"); +#endif + jsonWriteListStart(jw, track); if (isEmpty(chrom)) { struct bbiChromInfo *bci; for (bci = chromList; bci; bci = bci->next) { - bedDataOutput(jw, bbi, bci->name, 0, bci->size, maxItems); + bedDataOutput(jw, bbi, bci->name, 0, bci->size, maxItems, fiList); } } else - bedDataOutput(jw, bbi, chrom, uStart, uEnd, maxItems); + bedDataOutput(jw, bbi, chrom, uStart, uEnd, maxItems, fiList); jsonWriteListEnd(jw); } else if (startsWith("bigWig", thisTrack->type)) { unsigned maxItems = 1000; /* TBD will use this later for paging */ - jsonWriteListStart(jw, "trackData"); + jsonWriteObjectStart(jw, track); wigData(jw, bbi, chrom, uStart, uEnd, maxItems); - jsonWriteListEnd(jw); + jsonWriteObjectEnd(jw); } bbiFileClose(&bbi); jsonWriteObjectEnd(jw); fputs(jw->dy->string,stdout); } /* static void getHubTrackData(char *hubUrl) */ static void getTrackData() /* return data from a track, optionally just one chrom data, * optionally just one section of that chrom data */ { char *db = cgiOptionalString("db"); char *chrom = cgiOptionalString("chrom"); char *start = cgiOptionalString("start"); char *end = cgiOptionalString("end"); @@ -273,31 +276,31 @@ if (isEmpty(db)) apiErrAbort("missing URL variable db= name for endpoint '/getData/track"); if (isEmpty(table)) apiErrAbort("missing URL variable track= name for endpoint '/getData/track"); struct trackDb *thisTrack = hTrackDbForTrackAndAncestors(db, table); if (NULL == thisTrack) apiErrAbort("can not find track=%s name for endpoint '/getData/track", table); struct sqlConnection *conn = hAllocConn(db); if (! sqlTableExists(conn, table)) apiErrAbort("can not find specified 'track=%s' for endpoint: /getData/track?db=%s&track=%s", table, db, table); struct jsonWrite *jw = apiStartOutput(); jsonWriteString(jw, "db", db); -jsonWriteString(jw, "track", table); +// jsonWriteString(jw, "track", table); char *dataTime = sqlTableUpdate(conn, table); time_t dataTimeStamp = sqlDateToUnixTime(dataTime); replaceChar(dataTime, ' ', 'T'); /* ISO 8601 */ jsonWriteString(jw, "dataTime", dataTime); jsonWriteNumber(jw, "dataTimeStamp", (long long)dataTimeStamp); jsonWriteString(jw, "trackType", thisTrack->type); char query[4096]; unsigned chromSize = 0; struct bbiFile *bbi = NULL; struct bbiChromInfo *chromList = NULL; if (startsWith("big", thisTrack->type)) { char *bigDataUrl = trackDbSetting(thisTrack, "bigDataUrl"); @@ -305,111 +308,111 @@ bbi = bigFileOpen(thisTrack->type, bigDataUrl); else { char quickReturn[2048]; sqlSafef(query, sizeof(query), "select fileName from %s", table); if (sqlQuickQuery(conn, query, quickReturn, sizeof(quickReturn))) { bigDataUrl = cloneString(quickReturn); bbi = bigFileOpen(thisTrack->type, bigDataUrl); } } if (NULL == bbi) apiErrAbort("failed to find bigDataUrl=%s for track=%s in database=%s for endpoint '/getdata/track'", table, db); if (isNotEmpty(chrom)) { - jsonWriteString(jw, "chrom", chrom); +// jsonWriteString(jw, "chrom", chrom); chromSize = bbiChromSize(bbi, chrom); if (0 == chromSize) apiErrAbort("can not find specified chrom=%s in bigWig file URL %s", chrom, bigDataUrl); jsonWriteNumber(jw, "chromSize", (long long)chromSize); } else { chromList = bbiChromList(bbi); jsonWriteNumber(jw, "chromCount", (long long)slCount(chromList)); } jsonWriteString(jw, "bigDataUrl", bigDataUrl); } unsigned uStart = 0; unsigned uEnd = chromSize; if ( ! (isEmpty(start) || isEmpty(end)) ) { uStart = sqlUnsigned(start); uEnd = sqlUnsigned(end); jsonWriteNumber(jw, "start", uStart); jsonWriteNumber(jw, "end", uEnd); } if (startsWith("bigBed", thisTrack->type)) { struct asObject *as = bigBedAsOrDefault(bbi); - struct sqlFieldType *fi, *fiList = sqlFieldTypesFromAs(as); - jsonWriteListStart(jw, "columnNames"); + struct sqlFieldType *fiList = sqlFieldTypesFromAs(as); unsigned maxItems = 1000; /* TBD will use this later for paging */ +#ifdef NOT + jsonWriteListStart(jw, "columnNames"); // int columnCount = slCount(fiList); for (fi = fiList; fi; fi = fi->next) { jsonWriteObjectStart(jw, NULL); jsonWriteString(jw, fi->name, fi->type); jsonWriteObjectEnd(jw); } jsonWriteListEnd(jw); - jsonWriteListStart(jw, "trackData"); +#endif + jsonWriteListStart(jw, table); if (isEmpty(chrom)) { struct bbiChromInfo *bci; for (bci = chromList; bci; bci = bci->next) { - bedDataOutput(jw, bbi, bci->name, 0, bci->size, maxItems); + bedDataOutput(jw, bbi, bci->name, 0, bci->size, maxItems, fiList); } } else - bedDataOutput(jw, bbi, chrom, uStart, uEnd, maxItems); + bedDataOutput(jw, bbi, chrom, uStart, uEnd, maxItems, fiList); jsonWriteListEnd(jw); } else if (startsWith("bigWig", thisTrack->type)) { unsigned maxItems = 1000; /* TBD will use this later for paging */ - jsonWriteListStart(jw, "trackData"); + jsonWriteObjectStart(jw, table); wigData(jw, bbi, chrom, uStart, uEnd, maxItems); - jsonWriteListEnd(jw); + jsonWriteObjectEnd(jw); bbiFileClose(&bbi); } else if (isEmpty(chrom)) { /* no chrom specified, return entire table */ sqlSafef(query, sizeof(query), "select * from %s", table); tableDataOutput(conn, jw, query, table); } else if (isEmpty(start) || isEmpty(end)) { if (! sqlColumnExists(conn, table, "chrom")) apiErrAbort("track '%s' is not a position track, request track without chrom specification, genome: '%s'", table, db); - jsonWriteString(jw, "chrom", chrom); struct chromInfo *ci = hGetChromInfo(db, chrom); jsonWriteNumber(jw, "start", (long long)0); jsonWriteNumber(jw, "end", (long long)ci->size); sqlSafef(query, sizeof(query), "select * from %s where chrom='%s'", table, chrom); tableDataOutput(conn, jw, query, table); } else { if (! sqlColumnExists(conn, table, "chrom")) apiErrAbort("track '%s' is not a position track, request track without chrom specification, genome: '%s'", table, db); - jsonWriteString(jw, "chrom", chrom); jsonWriteNumber(jw, "start", (long long)sqlSigned(start)); jsonWriteNumber(jw, "end", (long long)sqlSigned(end)); sqlSafef(query, sizeof(query), "select * from %s where chrom='%s' AND chromEnd > %d AND chromStart < %d", table, chrom, sqlSigned(start), sqlSigned(end)); tableDataOutput(conn, jw, query, table); } jsonWriteObjectEnd(jw); fputs(jw->dy->string,stdout); hFreeConn(&conn); } static void getSequenceData() /* return DNA sequence, given at least a db=name and chrom=chr, optionally start and end */ { char *db = cgiOptionalString("db");