b20d369b166f18509c1fd18682ffc4fc5a5aac09 braney Thu Aug 21 17:38:37 2025 -0700 working on detail page for quickLift Chain. diff --git src/hg/lib/quickLift.c src/hg/lib/quickLift.c index 4389e8ce638..f333560c9db 100644 --- src/hg/lib/quickLift.c +++ src/hg/lib/quickLift.c @@ -8,30 +8,46 @@ #include "float.h" #include "asParse.h" #include "chain.h" #include "binRange.h" #include "basicBed.h" #include "liftOver.h" #include "hash.h" #include "bigBed.h" #include "bbiFile.h" #include "chainNetDbLoad.h" #include "hdb.h" #include "jksql.h" #include "hgConfig.h" #include "quickLift.h" #include "bigChain.h" +#include "bigLink.h" +#include "chromAlias.h" + +#define QUICKTYPE_INSERT 0 +#define QUICKTYPE_DEL 1 +#define QUICKTYPE_DOUBLE 2 +#define QUICKTYPE_MISMATCH 3 +#define QUICKTYPE_NOTHING 4 + +char *quickTypeStrings[] = +{ + "insert", + "deletion", + "double", + "mismatch" +}; struct bigBedInterval *quickLiftGetIntervals(char *quickLiftFile, struct bbiFile *bbi, char *chrom, int start, int end, struct hash **pChainHash) /* Return intervals from "other" species that will map to the current window. * These intervals are NOT YET MAPPED to the current assembly. */ { char *linkFileName = bigChainGetLinkFile(quickLiftFile); int maxGapBefore = 0; int maxGapAfter = 0; struct chain *chain, *chainList = chainLoadIdRangeHub(NULL, quickLiftFile, linkFileName, chrom, start, end, -1); struct lm *lm = lmInit(0); struct bigBedInterval *bbList = NULL, *bb; for(chain = chainList; chain; chain = chain->next) { @@ -246,15 +262,181 @@ if (error == NULL) { slAddHead(&liftedBedList, bed); } } return liftedBedList; } boolean quickLiftEnabled() /* Return TRUE if feature is available */ { char *cfgEnabled = cfgOption("browser.quickLift"); return cfgEnabled && (sameString(cfgEnabled, "on") || sameString(cfgEnabled, "true")) ; } + +static int hrCmp(const void *va, const void *vb) +/* Compare to sort based on chromStart. */ +{ +const struct quickLiftRegions *a = *((struct quickLiftRegions **)va); +const struct quickLiftRegions *b = *((struct quickLiftRegions **)vb); +return a->chromStart - b->chromStart; +} + +struct quickLiftRegions *quickLiftGetRegions(char *ourDb, char *liftDb, char *quickLiftFile, char *chrom, int seqStart, int seqEnd) +/* Figure out the highlight regions and cache them. */ +{ +static struct hash *highLightsHash = NULL; +struct quickLiftRegions *hrList = NULL; + +unsigned lengthLimit = atoi(cfgOptionDefault("quickLift.lengthLimit", "10000")); +if (seqEnd - seqStart > lengthLimit) + return hrList; + +if (highLightsHash != NULL) + { + if ((hrList = (struct quickLiftRegions *)hashFindVal(highLightsHash, quickLiftFile)) != NULL) + return hrList; + } +else + { + highLightsHash = newHash(0); + } + + +struct bbiFile *bbiChain = bigBedFileOpenAlias(quickLiftFile, chromAliasFindAliases); +struct lm *lm = lmInit(0); +struct bigBedInterval *bbChain, *bbChainList = bigBedIntervalQuery(bbiChain, chrom, seqStart, seqEnd, 0, lm); +char *links = bigChainGetLinkFile(quickLiftFile); +struct bbiFile *bbiLink = bigBedFileOpenAlias(links, chromAliasFindAliases); +struct bigBedInterval *bbLink, *bbLinkList = bigBedIntervalQuery(bbiLink, chrom, seqStart, seqEnd, 0, lm); + +char *chainRow[1024]; +char *linkRow[1024]; +char startBuf[16], endBuf[16]; + +for (bbChain = bbChainList; bbChain != NULL; bbChain = bbChain->next) + { + bigBedIntervalToRow(bbChain, chrom, startBuf, endBuf, chainRow, ArraySize(chainRow)); + struct bigChain *bc = bigChainLoad(chainRow); + + int previousTEnd = -1; + int previousQEnd = -1; + for (bbLink = bbLinkList; bbLink != NULL; bbLink = bbLink->next) + { + bigBedIntervalToRow(bbLink, chrom, startBuf, endBuf, linkRow, ArraySize(linkRow)); + struct bigLink *bl = bigLinkLoad(linkRow); + + if (!sameString(bl->name, bc->name)) + continue; + + int tStart = bl->chromStart; + int tEnd = bl->chromEnd; + int qStart = bl->qStart; + int qEnd = qStart + (tEnd - tStart); + // crop the chain block if it's bigger than the window + int tMin, tMax; + int qMin, qMax; + tMin = bl->chromStart; + tMax = bl->chromEnd; + qMin = bl->qStart; + if (seqStart > bl->chromStart) + { + tMin = seqStart; + qMin = qStart + (seqStart - bl->chromStart); + } + if (seqEnd < bl->chromEnd) + { + tMax = seqEnd; + } + qMax = qMin + (tMax - tMin); + + if (bc->strand[0] == '-') + { + qMin = bc->qSize - qMax; + qMax = qMin + (tMax - tMin); + } + + struct quickLiftRegions *hr; + AllocVar(hr); + slAddHead(&hrList, hr); + hr->chromStart = tMin; + hr->chromEnd = tMax; + hr->oChromStart = qMin; + hr->oChromEnd = qMax; + //jhr->type = highlightColors[NOTHING]; + hr->type = QUICKTYPE_NOTHING; + hr->id = bc->name; + + struct dnaSeq *tSeq = hDnaFromSeq(ourDb, chrom, tMin, tMax, dnaUpper); + struct dnaSeq *qSeq = hDnaFromSeq(liftDb, bc->qName, qMin, qMax, dnaUpper); + if (bc->strand[0] == '-') + reverseComplement(qSeq->dna, qSeq->size); + if ((previousTEnd != -1) && (previousTEnd == tStart)) + { + AllocVar(hr); + slAddHead(&hrList, hr); + hr->chromStart = previousTEnd; + hr->chromEnd = tStart; + hr->oChromStart = previousQEnd; + hr->oChromEnd = qStart; + hr->type = QUICKTYPE_DEL; + hr->otherBases = &qSeq->dna[qStart - qMin]; + hr->otherCount = hr->oChromEnd - hr->oChromStart; + hr->id = bc->name; + } + else if ( (previousQEnd != -1) && (previousQEnd == qStart)) + { + AllocVar(hr); + slAddHead(&hrList, hr); + hr->chromStart = previousTEnd; + hr->chromEnd = tStart; + hr->oChromStart = previousQEnd; + hr->oChromEnd = qStart; + hr->type = QUICKTYPE_INSERT; + hr->id = bc->name; + } + else if ( ((previousQEnd != -1) && (previousQEnd != qStart)) + && ((previousTEnd != -1) && (previousTEnd != tStart))) + { + AllocVar(hr); + slAddHead(&hrList, hr); + hr->chromStart = previousTEnd; + hr->chromEnd = tStart; + hr->oChromStart = previousQEnd; + hr->oChromEnd = qStart; + hr->type = QUICKTYPE_DOUBLE; + hr->id = bc->name; + } + + previousQEnd = qEnd; + previousTEnd = tEnd; + + + unsigned tAddr = tMin; + unsigned qAddr = qMin; + int count = 0; + for(; tAddr < tMax; tAddr++, qAddr++, count++) + { + if (tSeq->dna[count] != qSeq->dna[count]) + { + AllocVar(hr); + slAddHead(&hrList, hr); + hr->chromStart = tAddr; + hr->chromEnd = tAddr + 1; + hr->oChromStart = qAddr; + hr->oChromEnd = qAddr + 1; + hr->otherBases = &qSeq->dna[count]; + hr->otherCount = 1; + hr->type = QUICKTYPE_MISMATCH; + hr->id = bc->name; + } + } + } + } + +slSort(&hrList, hrCmp); +hashAdd(highLightsHash, quickLiftFile, hrList); + +return hrList; +}