353a34ac7e7638457db3f55e57452069113d860b braney Sun Sep 6 13:34:28 2026 -0700 Add a bigNet track type, a net of alignments in a bigBed, refs #20824 Track hubs have had no way to show a real net. The usual stand-in is a net rendered as a maf, which loses the level structure that makes a net useful for establishing orthologous sequence. bigNet holds the netAlign columns in a bigBed, so a hub can carry the net itself. The format is bed6+20: the target in chrom/chromStart/chromEnd, the query sequence in name, the query strand in strand, then level and the rest of the netAlign fields. The trackDb line is type bigNet mirroring type netAlign. chainTrack is the plain trackDb name of the bigChain track in the same hub; hgc adds the hub prefix itself. chainNetLoadRangeHub() builds a chainNet from a bigBed range query and hands it to the same helpToNet() the SQL path uses, so the nesting is rebuilt the same way. netDraw picks its loader off tg->isBigBed and the drawing code below that is untouched. genericNetClick does the same for the details page and follows the named chain track for the alignment. Also bounds the level walk in helpToNet() by help->maxDepth. It could read one past the end of the levels array. netToBigNet converts a net file to bedToBigBed input. It writes the tab line itself rather than calling bigNetTabOut, because autoSql prints a double with %g and that drops digits off a chain score. diff --git src/hg/lib/bigNet.c src/hg/lib/bigNet.c new file mode 100644 index 00000000000..59f358b0f71 --- /dev/null +++ src/hg/lib/bigNet.c @@ -0,0 +1,264 @@ +/* bigNet.c was originally generated by the autoSql program, which also + * generated bigNet.h and bigNet.sql. This module links the database and + * the RAM representation of objects. */ + +#include "common.h" +#include "linefile.h" +#include "dystring.h" +#include "jksql.h" +#include "bigNet.h" + + + +char *bigNetCommaSepFieldNames = "chrom,chromStart,chromEnd,name,score,strand,level,qStart,qEnd,chainId,ali,chainScore,type,qOver,qFar,qDup,tN,qN,tR,qR,tNewR,qNewR,tOldR,qOldR,tTrf,qTrf"; + +void bigNetStaticLoad(char **row, struct bigNet *ret) +/* Load a row from bigNet table into ret. The contents of ret will + * be replaced at the next call to this function. */ +{ + +ret->chrom = row[0]; +ret->chromStart = sqlUnsigned(row[1]); +ret->chromEnd = sqlUnsigned(row[2]); +ret->name = row[3]; +ret->score = sqlUnsigned(row[4]); +safecpy(ret->strand, sizeof(ret->strand), row[5]); +ret->level = sqlUnsigned(row[6]); +ret->qStart = sqlUnsigned(row[7]); +ret->qEnd = sqlUnsigned(row[8]); +ret->chainId = sqlUnsigned(row[9]); +ret->ali = sqlUnsigned(row[10]); +ret->chainScore = sqlDouble(row[11]); +ret->type = row[12]; +ret->qOver = sqlSigned(row[13]); +ret->qFar = sqlSigned(row[14]); +ret->qDup = sqlSigned(row[15]); +ret->tN = sqlSigned(row[16]); +ret->qN = sqlSigned(row[17]); +ret->tR = sqlSigned(row[18]); +ret->qR = sqlSigned(row[19]); +ret->tNewR = sqlSigned(row[20]); +ret->qNewR = sqlSigned(row[21]); +ret->tOldR = sqlSigned(row[22]); +ret->qOldR = sqlSigned(row[23]); +ret->tTrf = sqlSigned(row[24]); +ret->qTrf = sqlSigned(row[25]); +} + +struct bigNet *bigNetLoad(char **row) +/* Load a bigNet from row fetched with select * from bigNet + * from database. Dispose of this with bigNetFree(). */ +{ +struct bigNet *ret; + +AllocVar(ret); +ret->chrom = cloneString(row[0]); +ret->chromStart = sqlUnsigned(row[1]); +ret->chromEnd = sqlUnsigned(row[2]); +ret->name = cloneString(row[3]); +ret->score = sqlUnsigned(row[4]); +safecpy(ret->strand, sizeof(ret->strand), row[5]); +ret->level = sqlUnsigned(row[6]); +ret->qStart = sqlUnsigned(row[7]); +ret->qEnd = sqlUnsigned(row[8]); +ret->chainId = sqlUnsigned(row[9]); +ret->ali = sqlUnsigned(row[10]); +ret->chainScore = sqlDouble(row[11]); +ret->type = cloneString(row[12]); +ret->qOver = sqlSigned(row[13]); +ret->qFar = sqlSigned(row[14]); +ret->qDup = sqlSigned(row[15]); +ret->tN = sqlSigned(row[16]); +ret->qN = sqlSigned(row[17]); +ret->tR = sqlSigned(row[18]); +ret->qR = sqlSigned(row[19]); +ret->tNewR = sqlSigned(row[20]); +ret->qNewR = sqlSigned(row[21]); +ret->tOldR = sqlSigned(row[22]); +ret->qOldR = sqlSigned(row[23]); +ret->tTrf = sqlSigned(row[24]); +ret->qTrf = sqlSigned(row[25]); +return ret; +} + +struct bigNet *bigNetLoadAll(char *fileName) +/* Load all bigNet from a whitespace-separated file. + * Dispose of this with bigNetFreeList(). */ +{ +struct bigNet *list = NULL, *el; +struct lineFile *lf = lineFileOpen(fileName, TRUE); +char *row[26]; + +while (lineFileRow(lf, row)) + { + el = bigNetLoad(row); + slAddHead(&list, el); + } +lineFileClose(&lf); +slReverse(&list); +return list; +} + +struct bigNet *bigNetLoadAllByChar(char *fileName, char chopper) +/* Load all bigNet from a chopper separated file. + * Dispose of this with bigNetFreeList(). */ +{ +struct bigNet *list = NULL, *el; +struct lineFile *lf = lineFileOpen(fileName, TRUE); +char *row[26]; + +while (lineFileNextCharRow(lf, chopper, row, ArraySize(row))) + { + el = bigNetLoad(row); + slAddHead(&list, el); + } +lineFileClose(&lf); +slReverse(&list); +return list; +} + +struct bigNet *bigNetCommaIn(char **pS, struct bigNet *ret) +/* Create a bigNet out of a comma separated string. + * This will fill in ret if non-null, otherwise will + * return a new bigNet */ +{ +char *s = *pS; + +if (ret == NULL) + AllocVar(ret); +ret->chrom = sqlStringComma(&s); +ret->chromStart = sqlUnsignedComma(&s); +ret->chromEnd = sqlUnsignedComma(&s); +ret->name = sqlStringComma(&s); +ret->score = sqlUnsignedComma(&s); +sqlFixedStringComma(&s, ret->strand, sizeof(ret->strand)); +ret->level = sqlUnsignedComma(&s); +ret->qStart = sqlUnsignedComma(&s); +ret->qEnd = sqlUnsignedComma(&s); +ret->chainId = sqlUnsignedComma(&s); +ret->ali = sqlUnsignedComma(&s); +ret->chainScore = sqlDoubleComma(&s); +ret->type = sqlStringComma(&s); +ret->qOver = sqlSignedComma(&s); +ret->qFar = sqlSignedComma(&s); +ret->qDup = sqlSignedComma(&s); +ret->tN = sqlSignedComma(&s); +ret->qN = sqlSignedComma(&s); +ret->tR = sqlSignedComma(&s); +ret->qR = sqlSignedComma(&s); +ret->tNewR = sqlSignedComma(&s); +ret->qNewR = sqlSignedComma(&s); +ret->tOldR = sqlSignedComma(&s); +ret->qOldR = sqlSignedComma(&s); +ret->tTrf = sqlSignedComma(&s); +ret->qTrf = sqlSignedComma(&s); +*pS = s; +return ret; +} + +void bigNetFree(struct bigNet **pEl) +/* Free a single dynamically allocated bigNet such as created + * with bigNetLoad(). */ +{ +struct bigNet *el; + +if ((el = *pEl) == NULL) return; +freeMem(el->chrom); +freeMem(el->name); +freeMem(el->type); +freez(pEl); +} + +void bigNetFreeList(struct bigNet **pList) +/* Free a list of dynamically allocated bigNet's */ +{ +struct bigNet *el, *next; + +for (el = *pList; el != NULL; el = next) + { + next = el->next; + bigNetFree(&el); + } +*pList = NULL; +} + +void bigNetOutput(struct bigNet *el, FILE *f, char sep, char lastSep) +/* Print out bigNet. Separate fields with sep. Follow last field with lastSep. */ +{ +if (sep == ',') fputc('"',f); +fprintf(f, "%s", el->chrom); +if (sep == ',') fputc('"',f); +fputc(sep,f); +fprintf(f, "%u", el->chromStart); +fputc(sep,f); +fprintf(f, "%u", el->chromEnd); +fputc(sep,f); +if (sep == ',') fputc('"',f); +fprintf(f, "%s", el->name); +if (sep == ',') fputc('"',f); +fputc(sep,f); +fprintf(f, "%u", el->score); +fputc(sep,f); +if (sep == ',') fputc('"',f); +fprintf(f, "%s", el->strand); +if (sep == ',') fputc('"',f); +fputc(sep,f); +fprintf(f, "%u", el->level); +fputc(sep,f); +fprintf(f, "%u", el->qStart); +fputc(sep,f); +fprintf(f, "%u", el->qEnd); +fputc(sep,f); +fprintf(f, "%u", el->chainId); +fputc(sep,f); +fprintf(f, "%u", el->ali); +fputc(sep,f); +fprintf(f, "%g", el->chainScore); +fputc(sep,f); +if (sep == ',') fputc('"',f); +fprintf(f, "%s", el->type); +if (sep == ',') fputc('"',f); +fputc(sep,f); +fprintf(f, "%d", el->qOver); +fputc(sep,f); +fprintf(f, "%d", el->qFar); +fputc(sep,f); +fprintf(f, "%d", el->qDup); +fputc(sep,f); +fprintf(f, "%d", el->tN); +fputc(sep,f); +fprintf(f, "%d", el->qN); +fputc(sep,f); +fprintf(f, "%d", el->tR); +fputc(sep,f); +fprintf(f, "%d", el->qR); +fputc(sep,f); +fprintf(f, "%d", el->tNewR); +fputc(sep,f); +fprintf(f, "%d", el->qNewR); +fputc(sep,f); +fprintf(f, "%d", el->tOldR); +fputc(sep,f); +fprintf(f, "%d", el->qOldR); +fputc(sep,f); +fprintf(f, "%d", el->tTrf); +fputc(sep,f); +fprintf(f, "%d", el->qTrf); +fputc(lastSep,f); +} + +/* -------------------------------- End autoSql Generated Code -------------------------------- */ + + +int bigNetCmpTarget(const void *va, const void *vb) +/* Compare to sort based on target position, then by level. */ +{ +const struct bigNet *a = *((struct bigNet **)va); +const struct bigNet *b = *((struct bigNet **)vb); +int dif = strcmp(a->chrom, b->chrom); +if (dif == 0) + dif = a->chromStart - b->chromStart; +if (dif == 0) + dif = a->level - b->level; +return dif; +}