b475ddc8795329be93a783760d7aed704131d479 max Wed Feb 17 01:48:32 2021 -0800 adding JSON output to hgBlat, refs #27010 diff --git src/lib/psl.c src/lib/psl.c index f6b65c4..d438fda 100644 --- src/lib/psl.c +++ src/lib/psl.c @@ -160,30 +160,114 @@ } void pslFreeList(struct psl **pList) /* Free a list of dynamically allocated psl's */ { struct psl *el, *next; for (el = *pList; el != NULL; el = next) { next = el->next; pslFree(&el); } *pList = NULL; } +void pslOutputJson(struct psl *el, FILE *f) +/* print out psl as a json array */ +{ +fputs("[", f); +fprintf(f, "%u,", el->match); +fprintf(f, "%u,", el->misMatch); +fprintf(f, "%u,", el->repMatch); +fprintf(f, "%u,", el->nCount); +fprintf(f, "%u,", el->qNumInsert); +fprintf(f, "%d,", el->qBaseInsert); +fprintf(f, "%u,", el->tNumInsert); +fprintf(f, "%d,", el->tBaseInsert); +fprintf(f, "'%s',", el->strand); +fprintf(f, "'%s',", el->qName); +fprintf(f, "%u,", el->qSize); +fprintf(f, "%u,", el->qStart); +fprintf(f, "%u,", el->qEnd); +fprintf(f, "'%s',", el->tName); +fprintf(f, "%u,", el->tSize); +fprintf(f, "%u,", el->tStart); +fprintf(f, "%u,", el->tEnd); +fprintf(f, "%u,", el->blockCount); + +fputs("[", f); +for (int i=0; i<el->blockCount; ++i) + { + fprintf(f, "%u", el->blockSizes[i]); + if (i-1<el->blockCount) + fputc(',', f); + } +fputs("]", f); +fputs(",", f); + +fputs("[", f); +for (int i=0; i<el->blockCount; ++i) + { + fprintf(f, "%u", el->qStarts[i]); + if (i-1<el->blockCount) + fputc(',', f); // json does not allow trailing commas + } +fputs("]", f); +fputs(",", f); + +fputs("[", f); +for (int i=0; i<el->blockCount; ++i) + { + fprintf(f, "%u", el->tStarts[i]); + if (i-1<el->blockCount) + fputc(',', f); + } +fputs("]", f); + +if (el->qSequence) + { + fputc(',',f); + fputc('[',f); + for (int i=0; i<el->blockCount; ++i) + { + fprintf(f, "'%s'", el->qSequence[i]); + if (i-1<el->blockCount) + fputc(',', f); + } + fputc(']',f); + fputc(',',f); + + fputc('[',f); + for (int i=0; i<el->blockCount; ++i) + { + fprintf(f, "%s", el->tSequence[i]); + if (i-1<el->blockCount) + fputc(',', f); + } + fputc(']',f); + } + +if (ferror(f)) + { + perror("Error writing psl file\n"); + errAbort("\n"); + } + +fputs("]\n", f); +} + void pslOutput(struct psl *el, FILE *f, char sep, char lastSep) /* Print out psl. Separate fields with sep. Follow last field with lastSep. */ { int i; fprintf(f, "%u", el->match); fputc(sep,f); fprintf(f, "%u", el->misMatch); fputc(sep,f); fprintf(f, "%u", el->repMatch); fputc(sep,f); fprintf(f, "%u", el->nCount); fputc(sep,f); fprintf(f, "%u", el->qNumInsert); fputc(sep,f); fprintf(f, "%d", el->qBaseInsert); @@ -454,58 +538,84 @@ const struct psl *a = *((struct psl **)va); const struct psl *b = *((struct psl **)vb); return b->match - a->match; } static void pslLabelColumns(FILE *f) /* Write column info. */ { fputs("\n" "match\tmis- \trep. \tN's\tQ gap\tQ gap\tT gap\tT gap\tstrand\tQ \tQ \tQ \tQ \tT \tT \tT \tT \tblock\tblockSizes \tqStarts\t tStarts\n" " \tmatch\tmatch\t \tcount\tbases\tcount\tbases\t \tname \tsize\tstart\tend\tname \tsize\tstart\tend\tcount\n" "---------------------------------------------------------------------------------------------------------------------------------------------------------------\n", f); } +static void pslLabelColumnsJson(FILE *f) +/* Write column info as a JSON array */ +{ +fputs("['matches', 'misMatches', 'repMatches', 'nCount', 'qNumInsert', 'qBaseInsert', " + "'tNumInsert', 'tBaseInsert', 'strand', 'qName', 'qSize', 'qStart', 'qEnd', 'tName', " + "'tSize', 'tEnd', 'blockCount', 'blockSizes', 'qStarts', 'tStarts]", f); +} + void pslxWriteHead(FILE *f, enum gfType qType, enum gfType tType) /* Write header for extended (possibly protein) psl file. */ { fprintf(f, "psLayout version 4 %s %s\n", gfTypeName(qType), gfTypeName(tType)); pslLabelColumns(f); } void pslWriteHead(FILE *f) /* Write head of psl. */ { fputs("psLayout version 3\n", f); pslLabelColumns(f); } void pslWriteAll(struct psl *pslList, char *fileName, boolean writeHeader) /* Write a psl file from list. */ { FILE *f; struct psl *psl; f = mustOpen(fileName, "w"); if (writeHeader) pslWriteHead(f); for (psl = pslList; psl != NULL; psl = psl->next) pslTabOut(psl, f); fclose(f); } +void pslWriteAllJson(struct psl *pslList, FILE *f, boolean writeHeader) +/* Write a psl file from list as a json array . */ +{ +fputs("[\n", f); +if (writeHeader) + pslLabelColumnsJson(f); +fputs(",\n", f); + +for (struct psl *psl = pslList; psl; psl = psl->next) + { + pslOutputJson(psl, f); + if (psl->next) + fputs(",\n", f); + } + +puts("]\n"); +} + void pslxFileOpen(char *fileName, enum gfType *retQueryType, enum gfType *retTargetType, struct lineFile **retLf) /* Read header part of psl and make sure it's right. Return * sequence types and file handle. */ { char *line; int lineSize; char *words[30]; char *version; int wordCount; int i; enum gfType qt = gftRna, tt = gftDna; struct lineFile *lf = lineFileOpen(fileName, TRUE); if (!lineFileNext(lf, &line, &lineSize)) warn("%s is empty", fileName);