char *describeSubtrackMerge(char *linePrefix) /* Return a multi-line string that describes the specified subtrack merge, * with each line beginning with linePrefix. */ { struct dyString *dy = dyStringNew(512); struct trackDb *primary = subTdbFind(curTrack,curTable), *tdb = NULL; dyStringAppend(dy, linePrefix); dyStringPrintf(dy, "Subtrack merge, primary table = %s (%s)\n", curTable, primary->longLabel); dyStringAppend(dy, linePrefix); dyStringPrintf(dy, "Subtrack merge operation: "); if (isWiggle(database, curTable) || isBedGraph(curTable) || isBigWigTable(curTable)) { char *op = cartString(cart, hgtaSubtrackMergeWigOp); dyStringPrintf(dy, "%s of %s and selected subtracks:\n", op, curTable); } else { char *op = cartString(cart, hgtaSubtrackMergeOp); if (sameString(op, "any")) dyStringPrintf(dy, "All %s records that have any overlap with " "any other selected subtrack:\n", curTable); else if (sameString(op, "none")) dyStringPrintf(dy, "All %s records that have no overlap with " "any other selected subtrack:\n", curTable); else if (sameString(op, "more")) { dyStringPrintf(dy, "All %s records that have at least %s ", curTable, cartString(cart, hgtaNextSubtrackMergeMoreThreshold)); dyStringPrintf(dy, " %% overlap with any other selected subtrack:\n"); } else if (sameString(op, "less")) { dyStringPrintf(dy, "All %s records that have at most %s ", curTable, cartString(cart, hgtaNextSubtrackMergeLessThreshold)); dyStringPrintf(dy, " %% overlap with any other selected subtrack:\n"); } else if (sameString(op, "cat")) dyStringPrintf(dy, "All %s records, as well as all records from " "all other selected subtracks:\n", curTable); else if (sameString(op, "and")) dyStringPrintf(dy, "Base-pair-wise intersection (AND) of %s and " "other selected subtracks:\n", curTable); else if (sameString(op, "or")) dyStringPrintf(dy, "Base-pair-wise union (OR) of %s and other " "selected subtracks:\n", curTable); else errAbort("describeSubtrackMerge: unrecognized op %s", op); } struct slRef *tdbRef, *tdbRefList = trackDbListGetRefsToDescendantLeaves(curTrack->subtracks); for (tdbRef = tdbRefList; tdbRef != NULL; tdbRef = tdbRef->next) { tdb = tdbRef->val; if (!sameString(tdb->table, curTable) && isSubtrackMerged(tdb->table) && sameString(tdb->type, primary->type)) { dyStringAppend(dy, linePrefix); dyStringPrintf(dy, " %s (%s)\n", tdb->table, tdb->longLabel); } } return dyStringCannibalize(&dy); }
struct dataVector *mergedWigDataVector(char *table, struct sqlConnection *conn, struct region *region) /* Perform the specified subtrack merge wiggle-operation on table and * all other selected subtracks and intersect if necessary. */ { struct trackDb *tdb1 = hTrackDbForTrack(database, table); struct trackTable *tt1 = trackTableNew(tdb1, table, conn); struct dataVector *dataVector1 = dataVectorFetchOneRegion(tt1, region, conn); struct trackDb *cTdb = hCompositeTrackDbForSubtrack(database, tdb1); int numSubtracks = 1; char *op = cartString(cart, hgtaSubtrackMergeWigOp); boolean requireAll = cartBoolean(cart, hgtaSubtrackMergeRequireAll); boolean useMinScore = cartBoolean(cart, hgtaSubtrackMergeUseMinScore); float minScore = atof(cartString(cart, hgtaSubtrackMergeMinScore)); if (cTdb == NULL) errAbort("mergedWigDataVector: could not find parent/composite trackDb " "entry for subtrack %s", table); if (dataVector1 == NULL) { return NULL; } struct slRef *tdbRefList = trackDbListGetRefsToDescendantLeaves(cTdb->subtracks); struct slRef *tdbRef; for (tdbRef = tdbRefList; tdbRef != NULL; tdbRef = tdbRef->next) { struct trackDb *sTdb = tdbRef->val; if (isSubtrackMerged(sTdb->table) && ! sameString(tdb1->table, sTdb->table) && hSameTrackDbType(tdb1->type, sTdb->type)) { struct trackTable *tt2 = trackTableNew(sTdb, sTdb->table, conn); struct dataVector *dataVector2 = dataVectorFetchOneRegion(tt2, region, conn); numSubtracks++; if (dataVector2 == NULL) { if (requireAll) { freeDataVector(&dataVector1); return NULL; } continue; } if (sameString(op, "average") || sameString(op, "sum")) dataVectorSum(dataVector1, dataVector2, requireAll); else if (sameString(op, "product")) dataVectorProduct(dataVector1, dataVector2, requireAll); else if (sameString(op, "min")) dataVectorMin(dataVector1, dataVector2, requireAll); else if (sameString(op, "max")) dataVectorMax(dataVector1, dataVector2, requireAll); else errAbort("mergedWigOutRegion: unknown WigOp %s", op); dataVectorFree(&dataVector2); } } slFreeList(&tdbRefList); if (sameString(op, "average")) dataVectorNormalize(dataVector1, numSubtracks); if (useMinScore) dataVectorFilterMin(dataVector1, minScore); intersectDataVector(table, dataVector1, region, conn); return dataVector1; }
struct bed *getRegionAsMergedBed( char *db, char *table, /* Database and table. */ struct region *region, /* Region to get data for. */ char *filter, /* Filter to add to SQL where clause if any. */ struct hash *idHash, /* Restrict to id's in this hash if non-NULL. */ struct lm *lm, /* Where to allocate memory. */ int *retFieldCount) /* Number of fields. */ /* Return a bed list of all items in the given range in subtrack-merged table. * Cleanup result via lmCleanup(&lm) rather than bedFreeList. */ { if (! anySubtrackMerge(db, table)) return getRegionAsBed(db, table, region, filter, idHash, lm, retFieldCount); else { struct hTableInfo *hti = getHtiOnDb(database, table); int chromSize = hChromSize(database, region->chrom); Bits *bits1 = NULL; Bits *bits2 = NULL; struct bed *bedMerged = NULL; struct trackDb *subtrack = NULL; char *primaryType = findTypeForTable(database,curTrack,table, ctLookupName); char *op = cartString(cart, hgtaSubtrackMergeOp); boolean isBpWise = (sameString(op, "and") || sameString(op, "or")); double moreThresh = cartDouble(cart, hgtaSubtrackMergeMoreThreshold); double lessThresh = cartDouble(cart, hgtaSubtrackMergeLessThreshold); boolean firstTime = TRUE; if (sameString(op, "cat")) { struct bed *bedList = getRegionAsBed(db, table, region, filter, idHash, lm, retFieldCount); struct slRef *tdbRefList = trackDbListGetRefsToDescendantLeaves(curTrack->subtracks); struct slRef *tdbRef; for (tdbRef = tdbRefList; tdbRef != NULL; tdbRef = tdbRef->next) { subtrack = tdbRef->val; if (! sameString(curTable, subtrack->table) && isSubtrackMerged(subtrack->table) && sameString(subtrack->type, primaryType)) { struct bed *bedList2 = getRegionAsBed(db, subtrack->table, region, NULL, idHash, lm, retFieldCount); bedList = slCat(bedList, bedList2); } } slFreeList(&tdbRefList); return bedList; } bits1 = bitAlloc(chromSize+8); bits2 = bitAlloc(chromSize+8); /* If doing a base-pair-wise operation, then start with the primary * subtrack's ranges in bits1, and AND/OR all the selected subtracks' * ranges into bits1. If doing a non-bp-wise intersection, then * start with all bits clear in bits1, and then OR selected subtracks' * ranges into bits1. */ if (isBpWise) { struct lm *lm2 = lmInit(64*1024); struct bed *bedList1 = getRegionAsBed(db, table, region, filter, idHash, lm2, retFieldCount); bedOrBits(bits1, chromSize, bedList1, hti->hasBlocks, 0); lmCleanup(&lm2); } struct slRef *tdbRefList = trackDbListGetRefsToDescendantLeaves(curTrack->subtracks); struct slRef *tdbRef; for (tdbRef = tdbRefList; tdbRef != NULL; tdbRef = tdbRef->next) { subtrack = tdbRef->val; if (! sameString(curTable, subtrack->table) && isSubtrackMerged(subtrack->table) && sameString(subtrack->type, primaryType)) { struct hTableInfo *hti2 = getHtiOnDb(database, subtrack->table); struct lm *lm2 = lmInit(64*1024); struct bed *bedList2 = getRegionAsBed(db, subtrack->table, region, NULL, idHash, lm2, NULL); if (firstTime) firstTime = FALSE; else bitClear(bits2, chromSize); bedOrBits(bits2, chromSize, bedList2, hti2->hasBlocks, 0); if (sameString(op, "and")) bitAnd(bits1, bits2, chromSize); else bitOr(bits1, bits2, chromSize); lmCleanup(&lm2); } } slFreeList(&tdbRefList); if (isBpWise) { bedMerged = bitsToBed4List(bits1, chromSize, region->chrom, 1, region->start, region->end, lm); if (retFieldCount != NULL) *retFieldCount = 4; } else { struct bed *bedList1 = getRegionAsBed(db, table, region, filter, idHash, lm, retFieldCount); bedMerged = filterBedByOverlap(bedList1, hti->hasBlocks, op, moreThresh, lessThresh, bits1, chromSize); } bitFree(&bits1); bitFree(&bits2); return bedMerged; } }