0b9c2a6f9930555f65104385a9edcb00147a5bc6 braney Mon Feb 3 09:31:56 2025 -0800 add support for quikLifting mySQL beds. diff --git src/hg/hgTracks/bedTrack.c src/hg/hgTracks/bedTrack.c index 81271709e6d..5fa6411c17c 100644 --- src/hg/hgTracks/bedTrack.c +++ src/hg/hgTracks/bedTrack.c @@ -5,30 +5,31 @@ #include "common.h" #include "jksql.h" #include "bed.h" #include "hdb.h" #include "bedCart.h" #include "bbiFile.h" #include "bigBed.h" #include "hgTracks.h" #include "cds.h" #include "bedTabix.h" #include "obscure.h" #include "bigBedFilter.h" #include "bigBedLabel.h" #include "snake.h" +#include "liftOver.h" #include "quickLift.h" #define SEQ_DELIM '~' struct bed *bedLoadPairedTagAlign(char **row) /* Load first six fields of bed. * Add ~seq1~seq2 to end of name * Then remove the sequence to extra field when we convert to linkedFeature. * Assumes seq1 and seq2 are in row[6] and row[7], as they would be with a * pairedTagAlign type (hg/lib/encode/pairedTagAlign.as). It would be good to be * able to check these columns exist but we dont have the sqlResult here. */ { char buf[1024]; struct bed *ret = bedLoad6(row); safef(buf, sizeof(buf), "%s%c%s%c%s", ret->name, SEQ_DELIM, row[6], SEQ_DELIM, row[7]); @@ -128,64 +129,79 @@ bed->label = bigBedMakeLabel(tg->tdb, tg->labelColumns, bb, chromName); slAddHead(&list, bed); } if (filtered) labelTrackAsFilteredNumber(tg, filtered); lmCleanup(&lm); } else { char *table = tg->table; struct customTrack *ct = tg->customPt; struct sqlConnection *conn = NULL; + char *liftDb = cloneString(trackDbSetting(tg->tdb, "quickLiftDb")); + char *scoreFilterClause = getScoreFilterClause(cart, tg->tdb,NULL); + + if (liftDb != NULL) + { + struct hash *chainHash = newHash(8); + struct sqlConnection *conn = hAllocConn(liftDb); + char *quickLiftFile = cloneString(trackDbSetting(tg->tdb, "quickLiftUrl")); + bed = (struct bed *)quickLiftSql(conn, quickLiftFile, &tg->table[4], chromName, winStart, winEnd, NULL, scoreFilterClause, (ItemLoader)loader, chainHash); + + list = quickLiftBeds(bed, chainHash, FALSE); + hFreeConn(&conn); + } + else + { if (ct == NULL) conn = hAllocConnTrack(database, tg->tdb); else { conn = hAllocConn(CUSTOM_TRASH); table = ct->dbTableName; } struct sqlResult *sr = NULL; /* limit to items above a specified score */ - char *scoreFilterClause = getScoreFilterClause(cart, tg->tdb,NULL); if (doScoreCtFilter && (topTable != NULL) && hTableExists(database, topTable)) { sqlSafef(query, sizeof(query),"select * from %s order by score desc limit %d", topTable, scoreFilterCt); sr = sqlGetResult(conn, query); rowOffset = hOffsetPastBin(database, hDefaultChrom(database), topTable); } else if(scoreFilterClause != NULL && tg->bedSize >= 5) { sr = hRangeQuery(conn, table, chromName, winStart, winEnd, scoreFilterClause, &rowOffset); } else { sr = hRangeQuery(conn, table, chromName, winStart, winEnd, NULL, &rowOffset); } freeMem(scoreFilterClause); while ((row = sqlNextRow(sr)) != NULL) { bed = loader(row+rowOffset); slAddHead(&list, bed); } sqlFreeResult(&sr); hFreeConn(&conn); } + } if (doScoreCtFilter) { /* filter out items not in this window */ struct bed *newList = bedFilterListInRange(list, NULL, chromName, winStart, winEnd); list = newList; } slReverse(&list); tg->items = list; } void loadSimpleBed(struct track *tg) /* Load the items in one track - just move beds in * window... */ { @@ -512,57 +528,83 @@ boolean useItemRgb = FALSE; useItemRgb = bedItemRgb(tdb); if (tg->isBigBed) { // avoid opening an unneeded db connection for bigBed; required not to use mysql for parallel fetch tracks struct bbiFile *bbi = fetchBbiForTrack(tg); bigBedLabelCalculateFields(cart, tg->tdb, bbi, &tg->labelColumns); bigBedAddLinkedFeaturesFrom(tg, chromName, winStart, winEnd, scoreMin, scoreMax, useItemRgb, 12, &lfList); } else { /* Use tg->tdb->track because subtracks inherit composite track's tdb * by default, and the variable is named after the composite track. */ - struct sqlConnection *conn = hAllocConn(database); + char *liftDb = cloneString(trackDbSetting(tg->tdb, "quickLiftDb")); char *scoreFilterClause = getScoreFilterClause(cart, tg->tdb,NULL); + + if (liftDb == NULL) + { + struct sqlConnection *conn = hAllocConn(database); if (scoreFilterClause != NULL) { sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd,scoreFilterClause, &rowOffset); freeMem(scoreFilterClause); } else { sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd, NULL, &rowOffset); } while ((row = sqlNextRow(sr)) != NULL) { bed = bedLoad12(row+rowOffset); adjustBedScoreGrayLevel(tdb, bed, scoreMin, scoreMax); lf = lfFromBedExtra(bed, scoreMin, scoreMax); if (useItemRgb) { lf->useItemRgb = TRUE; lf->filterColor=bed->itemRgb; } slAddHead(&lfList, lf); bedFree(&bed); } sqlFreeResult(&sr); hFreeConn(&conn); } + else + { + struct hash *chainHash = newHash(8); + struct sqlConnection *conn = hAllocConn(liftDb); + char *quickLiftFile = cloneString(trackDbSetting(tg->tdb, "quickLiftUrl")); + bed = (struct bed *)quickLiftSql(conn, quickLiftFile, &tg->table[4], chromName, winStart, winEnd, NULL, scoreFilterClause, (ItemLoader)bedLoad12, chainHash); + + struct bed *liftedBeds = quickLiftBeds(bed, chainHash, TRUE); + for(bed = liftedBeds; bed; bed = bed->next) + { + lf = lfFromBedExtra(bed, scoreMin, scoreMax); + if (useItemRgb) + { + lf->useItemRgb = TRUE; + lf->filterColor=bed->itemRgb; + } + slAddHead(&lfList, lf); + } + hFreeConn(&conn); + } + } + slReverse(&lfList); if(tg->extraUiData) filterBed(tg, &lfList); slSort(&lfList, linkedFeaturesCmp); tg->items = lfList; filterItemsOnNames(tg); maybeLoadSnake(tg); // if we're in snake mode, change the methods } Color colorFromCart(struct track *tg, Color color) /* Return the RGB color from the cart setting 'colorOverride' or just return color */ { char varName[1024]; safef(varName, sizeof(varName), "%s.%s", tg->tdb->track, "colorOverride"); char *hexColorStr = cartOptionalString(cart, varName);