4bb9e8caea515342ba98d3871da76cd4ec69916f chmalee Fri May 1 14:10:00 2026 -0700 Initial myVariants implementation: a form on hgTracks where users can enter item details in one of three ways: hgvs/item search, simple bed form, advanced bed form where additional non-bed fields can dynamically created. Allows changing the color of items, writing descriptions, and editing the items after creation. Show overlaps with hardcoded tracks when hgc page is open (not in the hgc dialog). Next commit has implementation of sharing these tracks with other users diff --git src/hg/lib/customFactory.c src/hg/lib/customFactory.c index 4f429ba9e5c..3be82da25ab 100644 --- src/hg/lib/customFactory.c +++ src/hg/lib/customFactory.c @@ -25,31 +25,31 @@ #include "hdb.h" #include "hui.h" #include "customTrack.h" #include "customPp.h" #include "customFactory.h" #include "trashDir.h" #include "jsHelper.h" #include "encode/encodePeak.h" #include "udc.h" #include "bbiFile.h" #include "bigWig.h" #include "bigBed.h" #include "hgBam.h" #include "vcf.h" #include "vcfUi.h" -#include "makeItemsItem.h" +#include "myVariants.h" #include "bedDetail.h" #include "pgSnp.h" #include "regexHelper.h" #include "chromInfo.h" #include "grp.h" #include "trackHub.h" #include "bedTabix.h" #include "barChartBed.h" #include "barChartUi.h" #include "interact.h" #include "interactUi.h" #include "hic.h" #include "cgiApoptosis.h" #include "chromAlias.h" #include "bedMethyl.h" @@ -3366,45 +3366,45 @@ track->dbTrackType = cloneString("vcfPhasedTrio"); else track->dbTrackType = cloneString("vcfTabix"); return track; } static struct customFactory vcfTabixFactory = /* Factory for vcfTabix tracks */ { NULL, "vcfTabix", vcfTabixRecognizer, vcfTabixLoader, }; -/*** makeItems Factory - for track where user interactively creates items. ***/ +/*** myVariants Factory - for track where user interactively creates items. ***/ -static boolean makeItemsRecognizer(struct customFactory *fac, struct customPp *cpp, char *type, +static boolean myVariantsRecognizer(struct customFactory *fac, struct customPp *cpp, char *type, struct customTrack *track) -/* Return TRUE if looks like we're handling a makeItems track */ +/* Return TRUE if looks like we're handling a myVariants track */ { -return (sameType(type, "makeItems")); +return (sameType(type, "myVariants")); } -struct makeItemsItem *makeItemsItemFromRow(char **row, int rowSize) -/* Create a makeItemsItem from a row of uncertain length. */ +struct myVariants *myVariantsFromRow(char **row, int rowSize) +/* Create a myVariants from a row of uncertain length. */ { if (rowSize < 3) - errAbort("err: need at least %d fields in a makeItems row, got %d", 3, rowSize); -struct makeItemsItem *item; + errAbort("err: need at least %d fields in a myVariants row, got %d", 3, rowSize); +struct myVariants *item; AllocVar(item); item->chrom = cloneString(row[0]); item->chromStart = sqlUnsigned(row[1]); item->chromEnd = sqlUnsigned(row[2]); item->bin = binFromRange(item->chromStart, item->chromEnd); if (rowSize > 3) item->name = cloneString(row[3]); else item->name = cloneString(""); if (rowSize > 4) item->score = sqlSigned(row[4]); if (rowSize > 5) item->strand[0] = row[5][0]; else item->strand[0] = '.'; @@ -3413,122 +3413,80 @@ else item->thickStart = item->chromStart; if (rowSize > 7) item->thickEnd = sqlUnsigned(row[7]); else item->thickEnd = item->chromEnd; if (rowSize > 8) item->itemRgb = bedParseRgb(row[8]); if (rowSize > 9) item->description = cloneString(row[9]); else item->description = cloneString(""); return item; } -static struct customTrack *makeItemsLoader(struct customFactory *fac, struct hash *chromHash, +static struct customTrack *myVariantsLoader(struct customFactory *fac, struct hash *chromHash, struct customPp *cpp, struct customTrack *track, boolean dbRequested) -/* Process the makeItems track line. */ +/* Process the myVariants track line. The data will already be loaded by jsCommandDispatch + * so not much to do here */ { char *ctDb = ctGenomeOrCurrent(track); -struct makeItemsItem *list = NULL; +struct myVariants *list = NULL; int fieldCount = 0; char *line; while ((line = customFactoryNextRealTilTrack(cpp)) != NULL) { char *row[8]; int wordCount = chopLine(line, row); struct lineFile *lf = cpp->fileStack; lineFileExpectAtLeast(lf, 3, wordCount); if (fieldCount == 0) fieldCount = wordCount; else if (fieldCount != wordCount) { - errAbort("error: some lines in makeItems type custom track have %d fields, others have %d", + errAbort("error: some lines in myVariants type custom track have %d fields, others have %d", fieldCount, wordCount); } - struct makeItemsItem *item = makeItemsItemFromRow(row, wordCount); + struct myVariants *item = myVariantsFromRow(row, wordCount); customFactoryCheckChromNameDb(ctDb, item->chrom, lf); slAddHead(&list, item); } -track->dbTrackType = cloneString("makeItems"); -track->tdb->type = cloneString("makeItems"); -if (fieldCount != 0) - { - char buf[16]; - safef(buf, sizeof(buf), "%d", fieldCount); - ctAddToSettings(track, "fieldCount", cloneString(buf)); - } - -/* If necessary add track offsets. */ -int offset = track->offset; -if (offset != 0) - { - /* Add track offsets if any */ - struct makeItemsItem *item; - for (item = list; item != NULL; item = item->next) - { - item->chromStart += offset; - item->chromEnd += offset; - } - track->offset = 0; /* so DB load later won't do this again */ - hashMayRemove(track->tdb->settingsHash, "offset"); /* nor the file reader*/ - } - -/* Load database */ -customFactorySetupDbTrack(track); -char *tableName = track->dbTableName; -char *tableFormat = -"CREATE TABLE %s (\n" -" bin int unsigned not null, # Bin for range index\n" -" chrom varchar(255) not null, # Reference sequence chromosome or scaffold\n" -" chromStart int unsigned not null, # Start position in chromosome\n" -" chromEnd int unsigned not null, # End position in chromosome\n" -" name varchar(255) not null, # Name of item - up to 16 chars\n" -" score int unsigned not null, # 0-1000. Higher numbers are darker.\n" -" strand char(1) not null, # + or - for strand\n" -" thickStart int unsigned not null, # Start of thick part\n" -" thickEnd int unsigned not null, # End position of thick part\n" -" itemRgb int unsigned not null, # RGB 8 bits each as in bed\n" -" description longblob not null, # Longer item description\n" -" id int auto_increment,\n" -" #Indices\n" -" PRIMARY KEY(id),\n" -" INDEX(chrom(16),bin)\n" -")"; -struct dyString *createSql = dyStringNew(0); -sqlDyStringPrintf(createSql, tableFormat, tableName); -struct sqlConnection *conn = hAllocConn(CUSTOM_TRASH); -if (sqlMaybeMakeTable(conn, tableName, createSql->string)) - { - struct makeItemsItem *item; - for (item = list; item != NULL; item = item->next) - makeItemsItemSaveToDb(conn, item, tableName, 1000+strlen(item->description)); - } -dyStringFree(&createSql); -hFreeConn(&conn); +track->dbTrackType = cloneString("myVariants"); +track->tdb->type = cloneString("myVariants"); +/* tdb->shortLabel holds the name= value from the track line at this point. + * Use it for track/table identity, then override the display labels + * from the shortLabel/longLabel settings if present. */ +track->tdb->table = track->tdb->shortLabel; +track->tdb->track = track->tdb->shortLabel; +char *sl = trackDbSetting(track->tdb, "shortLabel"); +if (isNotEmpty(sl)) + track->tdb->shortLabel = cloneString(sl); +char *ll = trackDbSetting(track->tdb, "longLabel"); +if (isNotEmpty(ll)) + track->tdb->longLabel = cloneString(ll); return track; } -static struct customFactory makeItemsFactory = -/* Factory for makeItems tracks */ +static struct customFactory myVariantsFactory = +/* Factory for myVariants tracks */ { NULL, - "makeItems", - makeItemsRecognizer, - makeItemsLoader, + "myVariants", + myVariantsRecognizer, + myVariantsLoader, }; /*** VCF Factory - for Variant Call Format tracks ***/ static boolean vcfRecognizer(struct customFactory *fac, struct customPp *cpp, char *type, struct customTrack *track) /* Return TRUE if looks like we're handling a vcf track */ { if (type != NULL && !sameType(type, fac->name)) return FALSE; boolean isVcf = headerStartsWith(cpp, "##fileformat=VCFv"); if (type != NULL && !isVcf) { @@ -3757,31 +3715,31 @@ slAddTail(&factoryList, &bigMethylFactory); slAddTail(&factoryList, &bedTabixFactory); slAddTail(&factoryList, &longTabixFactory); slAddTail(&factoryList, &bigChainFactory); slAddTail(&factoryList, &bigMafFactory); slAddTail(&factoryList, &bigDbSnpFactory); slAddTail(&factoryList, &bigBedFactory); slAddTail(&factoryList, &bedGraphFactory); slAddTail(&factoryList, µarrayFactory); slAddTail(&factoryList, &coloredExonFactory); slAddTail(&factoryList, &encodePeakFactory); slAddTail(&factoryList, &bedDetailFactory); slAddTail(&factoryList, &adjacencyFactory); slAddTail(&factoryList, &bamFactory); slAddTail(&factoryList, &vcfTabixFactory); - slAddTail(&factoryList, &makeItemsFactory); + slAddTail(&factoryList, &myVariantsFactory); slAddTail(&factoryList, &bigDataOopsFactory); slAddTail(&factoryList, &barChartFactory); slAddTail(&factoryList, &bigBarChartFactory); slAddTail(&factoryList, &interactFactory); slAddTail(&factoryList, &bigInteractFactory); slAddTail(&factoryList, &hicFactory); slAddTail(&factoryList, &bigRmskFactory); slAddTail(&factoryList, &bigLollyFactory); slAddTail(&factoryList, &bedMethylFactory); } } struct customFactory *customFactoryFind(char *genomeDb, struct customPp *cpp, char *type, struct customTrack *track) /* Figure out factory that can handle this track. The track is