3b48412a1e8b3124093c30330c3730e4e4522ca0 braney Sun Sep 2 13:01:35 2018 -0700 libify custom bigbed labels so they can be used in hgFind reports #21963 diff --git src/hg/hgTracks/bedTrack.c src/hg/hgTracks/bedTrack.c index e98e835..344ec58 100644 --- src/hg/hgTracks/bedTrack.c +++ src/hg/hgTracks/bedTrack.c @@ -3,109 +3,50 @@ /* Copyright (C) 2013 The Regents of the University of California * See README in this or parent directory for licensing information. */ #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" #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]); freez(&(ret->name)); ret->name = cloneString(buf); return ret; } -static void calculateLabelFields(struct track *track) -/* Figure out which fields are available to label a bigBed track. */ -{ -struct bbiFile *bbi = fetchBbiForTrack(track); -struct asObject *as = bigBedAsOrDefault(bbi); -struct slPair *labelList = buildFieldList(track->tdb, "labelFields", as); - -if (labelList == NULL) - { - // There is no labelFields entry in the trackDb. - // If there is a name, use it by default, otherwise no label by default - if (track->bedSize > 3) - slAddHead(&track->labelColumns, slIntNew(3)); - } -else if (sameString(labelList->name, "none")) - return; // no label -else - { - // what has the user said to use as a label - char cartVar[1024]; - safef(cartVar, sizeof cartVar, "%s.label", track->tdb->track); - struct hashEl *labelEl = cartFindPrefix(cart, cartVar); - struct hash *onHash = newHash(4); - - // fill hash with fields that should be used for labels - // first turn on all the fields that are in defaultLabelFields - struct slPair *defaultLabelList = buildFieldList(track->tdb, "defaultLabelFields", as); - if (defaultLabelList != NULL) - { - for(; defaultLabelList; defaultLabelList = defaultLabelList->next) - hashStore(onHash, defaultLabelList->name); - } - else - // no default list, use first entry in labelFields as default - hashStore(onHash, labelList->name); - - // use cart variables to tweak the default-on hash - for(; labelEl; labelEl = labelEl->next) - { - /* the field name is after the <trackName>.label string */ - char *fieldName = &labelEl->name[strlen(cartVar) + 1]; - - if (sameString((char *)labelEl->val, "1")) - hashStore(onHash, fieldName); - else if (sameString((char *)labelEl->val, "0")) - hashRemove(onHash, fieldName); - } - - struct slPair *thisLabel = labelList; - for(; thisLabel; thisLabel = thisLabel->next) - { - if (hashLookup(onHash, thisLabel->name)) - { - // put this column number in the list of columns to use to make label - slAddHead(&track->labelColumns, slIntNew(ptToInt(thisLabel->val))); - } - } - slReverse(&track->labelColumns); - } -} char *bedName(struct track *tg, void *item); void loadSimpleBedWithLoader(struct track *tg, bedItemLoader loader) /* Load the items in one track using specified loader - just move beds in window... */ { struct bed *bed, *list = NULL; char **row; int rowOffset; char *words[3]; int wordCt; char query[128]; bool doScoreCtFilter = FALSE; int scoreFilterCt = 0; char *setting; @@ -139,41 +80,41 @@ list = bedTabixReadBeds(btf, chromName, winStart, winEnd, loader); bedTabixFileClose(&btf); } else if (tg->isBigBed) { // avoid opening an unneeded db connection for bigBed; required not to use mysql for parallel fetch tracks struct lm *lm = lmInit(0); struct bigBedInterval *bb, *bbList = bigBedSelectRange(tg, chromName, winStart, winEnd, lm); char *bedRow[32]; char startBuf[16], endBuf[16]; struct bbiFile *bbi = fetchBbiForTrack(tg); struct bigBedFilter *filters = bigBedBuildFilters(cart, bbi, tg->tdb); if (tg->itemName == bedName && !trackDbSettingClosestToHomeOn(tg->tdb, "linkIdInName")) tg->itemName = bigBedItemName; - calculateLabelFields(tg); + bigBedLabelCalculateFields(cart, tg->tdb, bbi, &tg->labelColumns); for (bb = bbList; bb != NULL; bb = bb->next) { bigBedIntervalToRow(bb, chromName, startBuf, endBuf, bedRow, ArraySize(bedRow)); if (!bigBedFilterInterval(bedRow, filters)) continue; bed = loader(bedRow); // FIXME BRANEY: either disable for all tracks with NUM_FIELDS > label field or better, // fix how label is stored so it doesn't trash custom bed field if (differentString(tg->tdb->type, "bigInteract")) - bed->label = makeLabel(tg, bb); + bed->label = bigBedMakeLabel(tg->tdb, tg->labelColumns, bb, chromName); slAddHead(&list, bed); } lmCleanup(&lm); } else { char *table = tg->table; struct customTrack *ct = tg->customPt; struct sqlConnection *conn = NULL; if (ct == NULL) conn = hAllocConnTrack(database, tg->tdb); else { conn = hAllocConn(CUSTOM_TRASH); @@ -281,31 +222,32 @@ void loadBed9(struct track *tg) /* Convert bed 9 info in window to linked feature. (to handle itemRgb)*/ { struct trackDb *tdb = tg->tdb; struct bed *bed; struct linkedFeatures *lfList = NULL, *lf; int scoreMin = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMin", "0")); int scoreMax = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMax", "1000")); 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 - calculateLabelFields(tg); + struct bbiFile *bbi = fetchBbiForTrack(tg); + bigBedLabelCalculateFields(cart, tg->tdb, bbi, &tg->labelColumns); bigBedAddLinkedFeaturesFrom(tg, chromName, winStart, winEnd, scoreMin, scoreMax, useItemRgb, 9, &lfList); } else { struct sqlConnection *conn = hAllocConnTrack(database, tdb); struct sqlResult *sr; char **row; int rowOffset; char *scoreFilterClause = getScoreFilterClause(cart, tg->tdb,NULL); if (scoreFilterClause != NULL) { sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd,scoreFilterClause, &rowOffset); freeMem(scoreFilterClause); } @@ -332,31 +274,32 @@ void loadBed8(struct track *tg) /* Convert bed 8 info in window to linked feature. */ { struct bed *bed; struct linkedFeatures *lfList = NULL, *lf; struct trackDb *tdb = tg->tdb; int scoreMin = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMin", "0")); int scoreMax = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMax", "1000")); 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 - calculateLabelFields(tg); + struct bbiFile *bbi = fetchBbiForTrack(tg); + bigBedLabelCalculateFields(cart, tg->tdb, bbi, &tg->labelColumns); bigBedAddLinkedFeaturesFrom(tg, chromName, winStart, winEnd, scoreMin, scoreMax, useItemRgb, 8, &lfList); } else { struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr; char **row; int rowOffset; char *scoreFilterClause = getScoreFilterClause(cart, tg->tdb,NULL); if (scoreFilterClause != NULL) { sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd,scoreFilterClause, &rowOffset); freeMem(scoreFilterClause); } @@ -531,31 +474,32 @@ { struct sqlResult *sr; char **row; int rowOffset; struct bed *bed; struct linkedFeatures *lfList = NULL, *lf; struct trackDb *tdb = tg->tdb; int scoreMin = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMin", "0")); int scoreMax = atoi(trackDbSettingClosestToHomeOrDefault(tdb, "scoreMax", "1000")); 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 - calculateLabelFields(tg); + 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 *scoreFilterClause = getScoreFilterClause(cart, tg->tdb,NULL); if (scoreFilterClause != NULL) { sr = hRangeQuery(conn, tg->table, chromName, winStart, winEnd,scoreFilterClause, &rowOffset); freeMem(scoreFilterClause); } else