#include "pilercr.h" const int MAXIGAP = 5; static Trapezoid *free_traps = NULL; static Trapezoid eotrap; static Trapezoid *eoterm = &eotrap; static int HSORT(const void *l, const void *r) { FilterHit *x = (FilterHit *) l; FilterHit *y = (FilterHit *) r; return x->QFrom - y->QFrom; } Trapezoid *MergeFilterHits(const char *SeqT, int SeqLengthT, const char *SeqQ, int SeqLengthQ, bool Self, const FilterHit *FilterHits, int FilterHitCount, const FilterParams &FP, int *ptrTrapCount) { if (0 == FilterHitCount) { *ptrTrapCount = 0; return 0; } qsort((void *) FilterHits, FilterHitCount, sizeof(FilterHit), HSORT); #if DEBUG { // Verify sort order for (int i = 0; i < FilterHitCount-1; ++i) if (FilterHits[i+1].QFrom < FilterHits[i].QFrom) Quit("Build_Trapezoids: not sorted"); } #endif const int TubeWidth = FP.TubeOffset + FP.SeedDiffs; const int DPADDING = 2; const int BINWIDE = TubeWidth - 1; const int BPADDING = k + 2; const int LPADDING = DPADDING + BINWIDE; free_traps = NULL; eoterm = &eotrap; Trapezoid *traporder, *traplist, *tailend; Trapezoid *b, *f, *t; int i, nd, tp; int trapcount; #ifdef REPORT_SIZES int traparea; #endif #ifdef REPORT_SIZES traparea = 0; #endif eoterm->lft = SeqLengthQ+1+LPADDING; eoterm->rgt = SeqLengthQ+1; eoterm->bot = -1; eoterm->top = SeqLengthQ+1; eoterm->next = NULL; trapcount = 0; traporder = eoterm; traplist = NULL; for (i = 0; i < FilterHitCount; i++) { nd = - FilterHits[i].DiagIndex; if (Self && nd <= FP.SeedDiffs) continue; tp = FilterHits[i].QFrom - BPADDING; #ifdef TEST_TRAP printf(" Diag %d [%d,%d]\n", nd,FilterHits[i].QFrom,FilterHits[i].QTo); #endif f = NULL; // for b in traporder for (b = traporder; 1; b = t) { t = b->next; if (b->top < tp) { trapcount += 1; #ifdef REPORT_SIZES traparea += (b->top - b->bot + 1) * (b->rgt - b->lft + 1); #endif if (f == NULL) traporder = t; else f->next = t; b->next = traplist; traplist = b; } else if (nd > b->rgt + DPADDING) f = b; else if (nd >= b->lft - LPADDING) { if (nd+BINWIDE > b->rgt) b->rgt = nd+BINWIDE; if (nd < b->lft) b->lft = nd; if (FilterHits[i].QTo > b->top) b->top = FilterHits[i].QTo; if (f != NULL && f->rgt + DPADDING >= b->lft) { f->rgt = b->rgt; if (f->bot > b->bot) f->bot = b->bot; if (f->top < b->top) f->top = b->top; f->next = t; b->next = free_traps; free_traps = b; } else if (t != NULL && t->lft - DPADDING <= b->rgt) { b->rgt = t->rgt; if (b->bot > t->bot) b->bot = t->bot; if (b->top < t->top) b->top = t->top; b->next = t->next; t->next = free_traps; free_traps = t; t = b->next; f = b; } else f = b; break; } else { // Add to free_trap list if (free_traps == NULL) { free_traps = (Trapezoid *) malloc(sizeof(Trapezoid)); if (free_traps == NULL) Quit("out of memory Trapezoid scan FilterHits"); free_traps->next = NULL; } if (f == NULL) f = traporder = free_traps; else f = f->next = free_traps; free_traps = f->next; f->next = b; if (f->next == 0) Log("f->next [3] %x\n", f); f->top = FilterHits[i].QTo; f->bot = FilterHits[i].QFrom; f->lft = nd; f->rgt = f->lft + BINWIDE; f = b; break; } } #ifdef TEST_TRAP printf(" Blist:"); for (b = traporder; b != NULL; b = b->next) printf(" [%d,%d]x[%d,%d]", b->bot,b->top,b->lft,b->rgt); printf("\n"); #endif } for (b = traporder; b != eoterm; b = t) { t = b->next; trapcount += 1; #ifdef REPORT_SIZES traparea += (b->top - b->bot + 1) * (b->rgt - b->lft + 1); #endif b->next = traplist; traplist = b; } #ifdef REPORT_SIZES printf("\n %9d trapezoids of area %d (%f%% of matrix)\n", trapcount,traparea,(100.*trapcount/SeqLengthT)/SeqLengthQ); fflush(stdout); #endif { int lag, lst, lclip; int abot, atop; #ifdef TEST_TRAPTRIM printf("SeqQ trimming:\n"); #endif for (b = traplist; b != NULL; b = b->next) { lag = (b->bot-MAXIGAP)+1; if (lag < 0) lag = 0; lst = b->top+MAXIGAP; if (lst > SeqLengthQ) lst = SeqLengthQ; #ifdef TEST_TRAPTRIM printf(" [%d,%d]x[%d,%d] = %d\n", b->bot,b->top,b->lft,b->rgt,b->top - b->bot + 1); #endif for (i = lag; i < lst; i++) { if (CharToLetter[(unsigned char) (SeqQ[i])] >= 0) { if (i-lag >= MAXIGAP) { if (lag - b->bot > 0) { if (free_traps == NULL) { free_traps = (Trapezoid *) malloc(sizeof(Trapezoid)); if (free_traps == NULL) Quit("out of memory Trapezoid cutter"); free_traps->next = NULL; } t = free_traps->next; *free_traps = *b; b->next = free_traps; free_traps = t; b->top = lag; b = b->next; b->bot = i; trapcount += 1; } else b->bot = i; #ifdef TEST_TRAPTRIM printf(" Cut trap SeqQ[%d,%d]\n",lag,i); #endif } lag = i+1; } } if (i-lag >= MAXIGAP) b->top = lag; } #ifdef TEST_TRAPTRIM printf("SeqT trimming:\n"); #endif tailend = NULL; for (b = traplist; b != NULL; b = b->next) { if (b->top - b->bot < k) continue; abot = b->bot - b->rgt; atop = b->top - b->lft; #ifdef TEST_TRAPTRIM printf(" [%d,%d]x[%d,%d] = %d\n", b->bot,b->top,b->lft,b->rgt,b->top - b->bot + 1); #endif lag = (abot - MAXIGAP) + 1; if (lag < 0) lag = 0; lst = atop + MAXIGAP; if (lst > SeqLengthT) lst = SeqLengthT; lclip = abot; for (i = lag; i < lst; i++) { if (CharToLetter[(unsigned char) (SeqT[i])] >= 0) { if (i-lag >= MAXIGAP) { if (lag > lclip) { if (free_traps == NULL) { free_traps = (Trapezoid *) malloc(sizeof(Trapezoid)); if (free_traps == NULL) Quit("out of memory Trapezoid cutter"); free_traps->next = NULL; } t = free_traps->next; *free_traps = *b; b->next = free_traps; free_traps = t; #ifdef TEST_TRAPTRIM printf(" Clip to %d,%d\n",lclip,lag); #endif { int x, m; x = lclip + b->lft; if (b->bot < x) b->bot = x; x = lag + b->rgt; if (b->top > x) b->top = x; m = (b->bot + b->top) / 2; x = m - lag; if (b->lft < x) b->lft = x; x = m - lclip; if (b->rgt > x) b->rgt = x; #ifdef TEST_TRAPTRIM printf(" [%d,%d]x[%d,%d] = %d\n", b->bot,b->top,b->lft,b->rgt,b->top-b->bot+1); #endif } b = b->next; trapcount += 1; } lclip = i; } lag = i+1; } } if (i-lag < MAXIGAP) lag = atop; #ifdef TEST_TRAPTRIM printf(" Clip to %d,%d\n",lclip,lag); #endif { int x, m; x = lclip + b->lft; if (b->bot < x) b->bot = x; x = lag + b->rgt; if (b->top > x) b->top = x; m = (b->bot + b->top) / 2; x = m - lag; if (b->lft < x) b->lft = x; x = m - lclip; if (b->rgt > x) b->rgt = x; #ifdef TEST_TRAPTRIM printf(" [%d,%d]x[%d,%d] = %d\n", b->bot,b->top,b->lft,b->rgt,b->top-b->bot+1); #endif } tailend = b; } } if (tailend != NULL) { if (free_traps == NULL) { free_traps = (Trapezoid *) malloc(sizeof(Trapezoid)); if (free_traps == NULL) Quit("out of memory Trapezoid cutter"); free_traps->next = NULL; } tailend->next = free_traps; free_traps = traplist; } #ifdef REPORT_SIZES printf(" %9d trimmed trap.s of area %d (%f%% of matrix)\n", trapcount,traparea,(100.*trapcount/SeqLengthT)/SeqLengthQ); fflush(stdout); #endif *ptrTrapCount = trapcount; return traplist; } int SumTrapLengths(const Trapezoid *Traps) { int Sum = 0; for (const Trapezoid *T = Traps; T; T = T->next) { const int Length = T->top - T->bot; Sum += Length; } return Sum; }