void processLast(FILE *of, Config *config, struct lastCall *last, bam_hdr_t *hdr, int32_t tid, int32_t pos, int width, uint32_t nmethyl, uint32_t nunmethyl) { if(last->tid == tid && last->pos == pos) { nmethyl += last->nmethyl; nunmethyl += last->nunmethyl; writeCall(of, config, hdr->target_name[tid], pos, width, nmethyl, nunmethyl); last->tid = -1; } else { if(last->tid != -1) { writeCall(of, config, hdr->target_name[tid], pos, width, last->nmethyl+nmethyl, last->nunmethyl+nunmethyl); } last->tid = tid; last->pos = pos; last->nmethyl = nmethyl; last->nunmethyl = nunmethyl; } }
void CRecordingEngExtInterceptor::PopFunc(CRecorderFuncCall* func) { if (func != m_LastFunc) rehlds_syserror("%s: stack corrupted", __FUNCTION__); writeCall(!func->m_StartWritten, true, func->m_FuncCall); if (m_LastFunc->m_Prev == NULL) { m_LastFunc = m_RootFunc = NULL; } else { m_LastFunc = m_LastFunc->m_Prev; m_LastFunc->m_Next = NULL; } }
void CRecordingEngExtInterceptor::PushFunc(CRecorderFuncCall* func) { CRecorderFuncCall* cc = m_LastFunc; while (cc != NULL) { if (!cc->m_StartWritten) { writeCall(true, false, cc->m_FuncCall); cc->m_StartWritten = true; } cc = cc->m_Prev; } if (m_LastFunc != NULL) { m_LastFunc->m_Next = func; func->m_Next = NULL; func->m_Prev = m_LastFunc; m_LastFunc = func; } else { m_LastFunc = m_RootFunc = func; func->m_Next = func->m_Prev = NULL; } }
void extractCalls(Config *config) { bam_hdr_t *hdr = sam_hdr_read(config->fp); bam_mplp_t iter; int ret, tid, pos, i, seqlen, type, rv, o = 0; int beg0 = 0, end0 = 1u<<29; int n_plp; //This will need to be modified for multiple input files int ctid = -1; //The tid of the contig whose sequence is stored in "seq" int idxBED = 0, strand; uint32_t nmethyl = 0, nunmethyl = 0; const bam_pileup1_t **plp = NULL; char *seq = NULL, base; mplp_data *data = NULL; struct lastCall *lastCpG = NULL; struct lastCall *lastCHG = NULL; if(config->merge) { if(config->keepCpG) { lastCpG = calloc(1, sizeof(struct lastCall)); assert(lastCpG); lastCpG->tid = -1; } if(config->keepCHG) { lastCHG = calloc(1, sizeof(struct lastCall)); assert(lastCHG); lastCHG->tid = -1; } } data = calloc(1,sizeof(mplp_data)); if(data == NULL) { fprintf(stderr, "Couldn't allocate space for the data structure in extractCalls()!\n"); return; } data->config = config; data->hdr = hdr; if (config->reg) { if((data->iter = sam_itr_querys(config->bai, hdr, config->reg)) == 0) { fprintf(stderr, "failed to parse regions %s", config->reg); return; } } if(config->bedName) { config->bed = parseBED(config->bedName, hdr); if(config->bed == NULL) return; } plp = calloc(1, sizeof(bam_pileup1_t *)); //This will have to be modified for multiple input files if(plp == NULL) { fprintf(stderr, "Couldn't allocate space for the plp structure in extractCalls()!\n"); return; } //Start the pileup iter = bam_mplp_init(1, filter_func, (void **) &data); bam_mplp_init_overlaps(iter); bam_mplp_set_maxcnt(iter, config->maxDepth); while((ret = cust_mplp_auto(iter, &tid, &pos, &n_plp, plp)) > 0) { //Do we need to process this position? if (config->reg) { beg0 = data->iter->beg, end0 = data->iter->end; if ((pos < beg0 || pos >= end0)) continue; // out of the region requested } if(tid != ctid) { if(seq != NULL) free(seq); seq = faidx_fetch_seq(config->fai, hdr->target_name[tid], 0, faidx_seq_len(config->fai, hdr->target_name[tid]), &seqlen); if(seqlen < 0) { fprintf(stderr, "faidx_fetch_seq returned %i while trying to fetch the sequence for tid %i (%s)!\n",\ seqlen, tid, hdr->target_name[tid]); fprintf(stderr, "Note that the output will be truncated!\n"); return; } ctid = tid; } if(config->bed) { //Handle -l while((o = posOverlapsBED(tid, pos, config->bed, idxBED)) == -1) idxBED++; if(o == 0) continue; //Wrong strand } if(isCpG(seq, pos, seqlen)) { if(!config->keepCpG) continue; type = 0; } else if(isCHG(seq, pos, seqlen)) { if(!config->keepCHG) continue; type = 1; } else if(isCHH(seq, pos, seqlen)) { if(!config->keepCHH) continue; type = 2; } else { continue; } nmethyl = nunmethyl = 0; base = *(seq+pos); for(i=0; i<n_plp; i++) { if(plp[0][i].is_del) continue; if(plp[0][i].is_refskip) continue; if(config->bed) if(!readStrandOverlapsBED(plp[0][i].b, config->bed->region[idxBED])) continue; strand = getStrand((plp[0]+i)->b); if(strand & 1) { if(base != 'C' && base != 'c') continue; } else { if(base != 'G' && base != 'g') continue; } rv = updateMetrics(config, plp[0]+i); if(rv > 0) nmethyl++; else if(rv<0) nunmethyl++; } if(nmethyl+nunmethyl==0) continue; if(!config->merge || type==2) { writeCall(config->output_fp[type], config, hdr->target_name[tid], pos, 1, nmethyl, nunmethyl); } else { //Merge into per-CpG/CHG metrics if(type==0) { if(base=='G' || base=='g') pos--; processLast(config->output_fp[0], config, lastCpG, hdr, tid, pos, 2, nmethyl, nunmethyl); } else { if(base=='G' || base=='g') pos-=2; processLast(config->output_fp[1], config, lastCHG, hdr, tid, pos, 3, nmethyl, nunmethyl); } } } //Don't forget the last CpG/CHG if(config->merge) { if(config->keepCpG && lastCpG->tid != -1) { processLast(config->output_fp[0], config, lastCpG, hdr, tid, pos, 2, nmethyl, nunmethyl); } if(config->keepCHG && lastCHG->tid != -1) { processLast(config->output_fp[1], config, lastCHG, hdr, tid, pos, 3, nmethyl, nunmethyl); } } bam_hdr_destroy(hdr); if(data->iter) hts_itr_destroy(data->iter); bam_mplp_destroy(iter); free(data); free(plp); if(seq != NULL) free(seq); }