int premovemax(PHEAP* heap,struct SNPfrags* snpfrag, int* slist) { // easy to copy elements of the harray[0] element from the heap if (heap->length ==0) return -1; heap->elements[0] = heap->elements[heap->length-1]; snpfrag[slist[heap->elements[0]]].heaploc = 0; heap->length--; if (heap->length ==0) return 1; // swap root's value with the maximum of it's two children, maxHeapify pmaxHeapify(heap,0,snpfrag,slist); return 1; }
// function added 10/24/2014 void update_neighbor_scores(struct SNPfrags* snpfrag,int node,int startnode,int secondnode,struct fragment* Flist,char* hap,struct PHEAP* pheap,int* slist) { // for all vertices linked to node -> update score of the neighbors, can be done using list of fragments for snpfrag[node] int j=0,f=0,i=0,n=0,k=0,newnode=0; char allele,allele1; float q2,q1,p1,p2,ew,match; double oldscore=0; for (n=0;n<snpfrag[node].frags;n++) { f = snpfrag[node].flist[n]; // index into Flist global for (j=0;j<Flist[f].blocks;j++) // first find the allele at 'node' in the fragment 'f' { for (k=0;k<Flist[f].list[j].len;k++) { if (Flist[f].list[j].offset + k == node) { allele = Flist[f].list[j].hap[k]; q1 = Flist[f].list[j].pv[k]; } } } for (j=0;j<Flist[f].blocks;j++) { for (k=0;k<Flist[f].list[j].len;k++) { allele1 = Flist[f].list[j].hap[k]; q2 = Flist[f].list[j].pv[k]; newnode = Flist[f].list[j].offset + k; if (newnode == node || newnode == startnode || newnode == secondnode) continue; p1 = q1*q2+(1-q1)*(1-q2); p2 = q1*(1-q2)+q2*(1-q1); ew = log10(p1/p2); if (hap[node] == hap[Flist[f].list[j].offset + k] && allele == allele1) match = 1; else if (hap[node] != hap[Flist[f].list[j].offset + k] && allele != allele1) match = 1; else if (hap[node] == hap[Flist[f].list[j].offset + k] && allele != allele1) match = -1; else if (hap[node] != hap[Flist[f].list[j].offset + k] && allele == allele1) match = -1; if (snpfrag[node].parent == startnode) { oldscore = snpfrag[newnode].score; snpfrag[newnode].score += match*ew; } else if (snpfrag[node].parent == secondnode) { oldscore = snpfrag[newnode].score; snpfrag[newnode].score -= match*ew; } if (fabsf(oldscore) > fabsf(snpfrag[newnode].score)) // score decreased { pmaxHeapify(pheap,snpfrag[newnode].heaploc,snpfrag,slist); } else pbubbleUp(pheap,snpfrag[newnode].heaploc,snpfrag,slist); } } } }
// trickledown can also be used to update the PHEAP if the score of a node is decreased via an update void pmaxHeapify(PHEAP* heap,int node,struct SNPfrags* snpfrag, int* slist) { int lc = 2*node+1; int rc = 2*node + 2; int maxindex = node; int temp; // printf("inside maxheapify %d %d %d\n",lc,rc,node); if (rc >= heap->length) { if (lc < heap->length) maxindex = lc; } else { if (fabsf(snpfrag[slist[heap->elements[lc]]].score) >= fabsf(snpfrag[slist[heap->elements[rc]]].score)) maxindex = lc; else maxindex = rc; } if (fabsf(snpfrag[slist[heap->elements[node]]].score) < fabsf(snpfrag[slist[heap->elements[maxindex]]].score)) // swap and percolate down { //temp = snpfrag[slist[node]].heaploc; snpfrag[slist[node]].heaploc = snpfrag[slist[maxindex]].heaploc; snpfrag[slist[maxindex]].heaploc = temp; temp = heap->elements[node]; heap->elements[node] = heap->elements[maxindex]; heap->elements[maxindex] = temp; snpfrag[slist[heap->elements[node]]].heaploc = node; snpfrag[slist[heap->elements[maxindex]]].heaploc = maxindex; pmaxHeapify(heap,maxindex,snpfrag,slist); } }
void pbuildmaxheap(PHEAP* heap,struct SNPfrags* snpfrag, int* slist) { int i=0; for (i=heap->length/2-1;i>=0;i--) pmaxHeapify(heap,i,snpfrag,slist); //fprintf(stdout,"heapify %d hl %d\n",i,heap->length); }
void update_fragment_scores(struct SNPfrags* snpfrag, struct fragment* Flist, char* hap, int startnode, int secondnode, int node_added, struct PHEAP* pheap, int* slist) { int j = 0, f = 0, t = 0, n = 0, k = 0, node = 0; float prob, prob2; float scores[4]; float Lo, Ln; float Lo_htrans, Ln_htrans; float f_scores[4]; float htrans_f_scores[4]; float oldscore; int htrans_flipped = 0; for (n = 0; n < snpfrag[node_added].frags; n++){ f = snpfrag[node_added].flist[n]; // index into Flist global for (t = 0; t < 4; t++) f_scores[t] = Flist[f].scores[t]; // store previous fragment scores before updating for (t = 0; t < 4; t++) htrans_f_scores[t] = Flist[f].htscores[t]; // store previous fragment scores before updating j = snpfrag[node_added].jlist[n]; k = snpfrag[node_added].klist[n]; if (hap[Flist[f].list[j].offset + k] == '-' || (int) Flist[f].list[j].qv[k] - QVoffset < MINQ) continue; node = Flist[f].list[j].offset + k; if (node != node_added) continue; prob = QVoffset - (int) Flist[f].list[j].qv[k]; prob /= 10; // log10(e) prob2 = Flist[f].list[j].p1[k]; if (snpfrag[node].parent == startnode){ // if node is added to 'startnode', original and new likelihoods are updated identically if (hap[node] == Flist[f].list[j].hap[k]){ Flist[f].scores[0] += prob2; Flist[f].scores[1] += prob; Flist[f].scores[2] += prob2; Flist[f].scores[3] += prob; } else { Flist[f].scores[0] += prob; Flist[f].scores[1] += prob2; Flist[f].scores[2] += prob; Flist[f].scores[3] += prob2; } } else if (snpfrag[node].parent == secondnode){ if (hap[node] == Flist[f].list[j].hap[k]){ Flist[f].scores[0] += prob; Flist[f].scores[1] += prob2; Flist[f].scores[2] += prob; Flist[f].scores[3] += prob2; } else { Flist[f].scores[0] += prob2; Flist[f].scores[1] += prob; Flist[f].scores[2] += prob2; Flist[f].scores[3] += prob; } } if (HIC && Flist[f].data_type == 1){ // HiC read htrans_flipped = (Flist[f].mate2_ix != -1 && node >= Flist[f].mate2_ix); // are we flipped due to h-trans? if ((snpfrag[node].parent == startnode && !htrans_flipped) ||(snpfrag[node].parent == secondnode && htrans_flipped)){ // if node is added to 'startnode', original and new likelihoods are updated identically if (hap[node] == Flist[f].list[j].hap[k]){ Flist[f].htscores[0] += prob2; Flist[f].htscores[1] += prob; Flist[f].htscores[2] += prob2; Flist[f].htscores[3] += prob; } else { Flist[f].htscores[0] += prob; Flist[f].htscores[1] += prob2; Flist[f].htscores[2] += prob; Flist[f].htscores[3] += prob2; } }else if((snpfrag[node].parent == secondnode && !htrans_flipped) ||(snpfrag[node].parent == startnode && htrans_flipped)){ if (hap[node] == Flist[f].list[j].hap[k]){ Flist[f].htscores[0] += prob; Flist[f].htscores[1] += prob2; Flist[f].htscores[2] += prob; Flist[f].htscores[3] += prob2; } else { Flist[f].htscores[0] += prob2; Flist[f].htscores[1] += prob; Flist[f].htscores[2] += prob2; Flist[f].htscores[3] += prob; } } } for (j = 0; j < Flist[f].blocks; j++){ // update score of every node outside 2 shores covered by 'f' for (k = 0; k < Flist[f].list[j].len; k++) { if (hap[Flist[f].list[j].offset + k] == '-' || (int) Flist[f].list[j].qv[k] - QVoffset < MINQ) continue; node = Flist[f].list[j].offset + k; if (snpfrag[node].parent != startnode && snpfrag[node].parent != secondnode && node != node_added) { oldscore = snpfrag[node].score; // store old score prob = QVoffset - (int) Flist[f].list[j].qv[k]; prob /= 10; // log10(e) //prob1 = 1.0 - pow(10,prob); prob2 = log10(prob1); prob2 = Flist[f].list[j].p1[k]; for (t = 0; t < 4; t++) scores[t] = f_scores[t]; if (hap[node] == Flist[f].list[j].hap[k]) { scores[0] += prob2; scores[1] += prob; scores[2] += prob; scores[3] += prob2; } else { scores[0] += prob; scores[1] += prob2; scores[2] += prob2; scores[3] += prob; } Lo = addlogs(scores[0], scores[1]); Ln = addlogs(scores[2], scores[3]); if (HIC && Flist[f].data_type == 1){ // HiC Read htrans_flipped = (Flist[f].mate2_ix != -1 && node >= Flist[f].mate2_ix); // are we flipped due to h-trans? for (t = 0; t < 4; t++) scores[t] = htrans_f_scores[t]; if ((hap[node] == Flist[f].list[j].hap[k] && !htrans_flipped) ||(hap[node] != Flist[f].list[j].hap[k] && htrans_flipped)) { scores[0] += prob2; scores[1] += prob; scores[2] += prob; scores[3] += prob2; } else { scores[0] += prob; scores[1] += prob2; scores[2] += prob2; scores[3] += prob; } Lo_htrans = addlogs(scores[0], scores[1]); Ln_htrans = addlogs(scores[2], scores[3]); // update Lo and Ln for h-trans possibility Lo = addlogs(Lo+subtractlogs(0,Flist[f].htrans_prob), Lo_htrans+Flist[f].htrans_prob); Ln = addlogs(Ln+subtractlogs(0,Flist[f].htrans_prob), Ln_htrans+Flist[f].htrans_prob); } snpfrag[node].score -= Lo - Ln;; // subtract old score for variant for (t = 0; t < 4; t++) scores[t] = Flist[f].scores[t]; if (hap[node] == Flist[f].list[j].hap[k]) { scores[0] += prob2; scores[1] += prob; scores[2] += prob; scores[3] += prob2; } else { scores[0] += prob; scores[1] += prob2; scores[2] += prob2; scores[3] += prob; } Lo = addlogs(scores[0], scores[1]); Ln = addlogs(scores[2], scores[3]); if (HIC && Flist[f].data_type == 1){ // HiC read for (t = 0; t < 4; t++) scores[t] = Flist[f].htscores[t]; if ((hap[node] == Flist[f].list[j].hap[k] && !htrans_flipped) ||(hap[node] != Flist[f].list[j].hap[k] && htrans_flipped)) { scores[0] += prob2; scores[1] += prob; scores[2] += prob; scores[3] += prob2; } else { scores[0] += prob; scores[1] += prob2; scores[2] += prob2; scores[3] += prob; } Lo_htrans = addlogs(scores[0], scores[1]); Ln_htrans = addlogs(scores[2], scores[3]); // update Lo and Ln for h-trans possibility Lo = addlogs(Lo+subtractlogs(0,Flist[f].htrans_prob), Lo_htrans+Flist[f].htrans_prob); Ln = addlogs(Ln+subtractlogs(0,Flist[f].htrans_prob), Ln_htrans+Flist[f].htrans_prob); } snpfrag[node].score += Lo - Ln; // add new delta LL for variant if (fabsf(oldscore) > fabsf(snpfrag[node].score)){ // score decreased pmaxHeapify(pheap, snpfrag[node].heaploc, snpfrag, slist); } else pbubbleUp(pheap, snpfrag[node].heaploc, snpfrag, slist); } } } } }