static struct axt *axtFromBlocks( struct chain *chain, struct cBlock *startB, struct cBlock *endB, struct dnaSeq *qSeq, int qOffset, struct dnaSeq *tSeq, int tOffset) /* Convert a list of blocks (guaranteed not to have inserts in both * strands between them) to an axt. */ { int symCount = 0; int dq, dt, blockSize = 0, symIx = 0; struct cBlock *b, *a = NULL; struct axt *axt; char *qSym, *tSym; /* Make a pass through figuring out how big output will be. */ for (b = startB; b != endB; b = b->next) { if (a != NULL) { dq = b->qStart - a->qEnd; dt = b->tStart - a->tEnd; symCount += dq + dt; } blockSize = b->qEnd - b->qStart; symCount += blockSize; a = b; } /* Allocate axt and fill in most fields. */ AllocVar(axt); axt->qName = cloneString(chain->qName); axt->qStart = startB->qStart; axt->qEnd = a->qEnd; axt->qStrand = chain->qStrand; axt->tName = cloneString(chain->tName); axt->tStart = startB->tStart; axt->tEnd = a->tEnd; axt->tStrand = '+'; axt->symCount = symCount; axt->qSym = qSym = needLargeMem(symCount+1); qSym[symCount] = 0; axt->tSym = tSym = needLargeMem(symCount+1); tSym[symCount] = 0; /* Fill in symbols. */ a = NULL; for (b = startB; b != endB; b = b->next) { if (a != NULL) { dq = b->qStart - a->qEnd; dt = b->tStart - a->tEnd; if (dq == 0) { memset(qSym+symIx, '-', dt); memcpy(tSym+symIx, tSeq->dna + a->tEnd - tOffset, dt); symIx += dt; } else { assert(dt == 0); memset(tSym+symIx, '-', dq); memcpy(qSym+symIx, qSeq->dna + a->qEnd - qOffset, dq); symIx += dq; } } blockSize = b->qEnd - b->qStart; memcpy(qSym+symIx, qSeq->dna + b->qStart - qOffset, blockSize); memcpy(tSym+symIx, tSeq->dna + b->tStart - tOffset, blockSize); symIx += blockSize; a = b; } assert(symIx == symCount); /* Fill in score and return. */ axt->score = axtScoreDnaDefault(axt); return axt; }
static void saveAxtBundle(char *chromName, int chromSize, int chromOffset, struct ffAli *ali, struct dnaSeq *tSeq, struct hash *t3Hash, struct dnaSeq *qSeq, boolean qIsRc, boolean tIsRc, enum ffStringency stringency, int minMatch, struct gfOutput *out) /* Save alignment to axtBundle. */ { struct axtData *ad = out->data; struct ffAli *sAli, *eAli, *ff, *rt, *eFf = NULL; struct axt *axt; struct dyString *q = newDyString(1024), *t = newDyString(1024); struct axtBundle *gab; struct trans3 *t3List = NULL; if (t3Hash != NULL) t3List = hashMustFindVal(t3Hash, tSeq->name); AllocVar(gab); gab->tSize = chromSize; gab->qSize = qSeq->size; for (sAli = ali; sAli != NULL; sAli = eAli) { eAli = ffNextBreak(sAli, 8, tSeq, t3List); dyStringClear(q); dyStringClear(t); for (ff = sAli; ff != eAli; ff = ff->right) { dyStringAppendN(q, ff->nStart, ff->nEnd - ff->nStart); dyStringAppendN(t, ff->hStart, ff->hEnd - ff->hStart); rt = ff->right; if (rt != eAli) { int nGap = rt->nStart - ff->nEnd; int nhStart = trans3GenoPos(rt->hStart, tSeq, t3List, FALSE) + chromOffset; int ohEnd = trans3GenoPos(ff->hEnd, tSeq, t3List, TRUE) + chromOffset; int hGap = nhStart - ohEnd; int gap = max(nGap, hGap); if (nGap < 0 || hGap < 0) { errAbort("Negative gap size in %s vs %s", tSeq->name, qSeq->name); } if (nGap == gap) { dyStringAppendN(q, ff->nEnd, gap); dyStringAppendMultiC(t, '-', gap); } else { dyStringAppendN(t, ff->hEnd, gap); dyStringAppendMultiC(q, '-', gap); } } eFf = ff; /* Keep track of last block in bunch */ } assert(t->stringSize == q->stringSize); AllocVar(axt); axt->qName = cloneString(qSeq->name); axt->qStart = sAli->nStart - qSeq->dna; axt->qEnd = eFf->nEnd - qSeq->dna; axt->qStrand = (qIsRc ? '-' : '+'); axt->tName = cloneString(chromName); axt->tStart = trans3GenoPos(sAli->hStart, tSeq, t3List, FALSE) + chromOffset; axt->tEnd = trans3GenoPos(eFf->hEnd, tSeq, t3List, TRUE) + chromOffset; axt->tStrand = (tIsRc ? '-' : '+'); axt->symCount = t->stringSize; axt->qSym = cloneString(q->string); axt->tSym = cloneString(t->string); axt->frame = trans3Frame(sAli->hStart, t3List); if (out->qIsProt) axt->score = axtScoreProteinDefault(axt); else axt->score = axtScoreDnaDefault(axt); slAddHead(&gab->axtList, axt); } slReverse(&gab->axtList); dyStringFree(&q); dyStringFree(&t); slAddHead(&ad->bundleList, gab); }