ReturnValue np(iter_a const a, iter_a const ae, iter_b const b, iter_b const be, index_type const maxd = std::numeric_limits<index_type>::max()) { assert ( ae-a >= 0 ); assert ( be-b >= 0 ); size_t const an = ae-a; size_t const bn = be-b; if ( ! an || ! bn ) { return ReturnValue(0,0,0); } size_t const sn = std::max(an,bn); // number of diagonals index_type const numdiag = (sn<<1)+1; if ( numdiag > static_cast<index_type>(DE.size()) ) { DE.resize(numdiag); DO.resize(numdiag); } NPElement * DP = DE.begin() + sn; NPElement * DN = DO.begin() + sn; // diagonal containing bottom right of matrix int64_t fdiag = std::numeric_limits<int64_t>::max(); // how far do we get without an error? { index_type const s = slide<iter_a,iter_b,false>(a,ae,b,be,0); DP[0].offset = s; } if ( DP[0].offset >= static_cast<int64_t>(std::min(an,bn)) ) { assert ( DP[0].offset == static_cast<int64_t>(std::min(an,bn)) ); uint64_t const n = std::min(an,bn); return ReturnValue(n,n,0); } index_type d = 1; assert ( DP[0].offset < static_cast<int64_t>(std::min(an,bn)) ); { index_type const p = DP[0].offset; index_type const s = slide<iter_a,iter_b,true>(a,ae,b+1,be,p); DN[-1].offset = p + s; } { index_type const p = DP[0].offset+1; index_type const s = slide<iter_a,iter_b,false>(a,ae,b,be,p); DN[ 0].offset = p + s; } { index_type const p = DP[0].offset; index_type const s = slide<iter_a,iter_b,false>(a+1,ae,b,be,p); DN[ 1].offset = p + s; } d += 1; std::swap(DP,DN); for ( ; d < maxd ; ++d ) { // std::cerr << "d=" << d << std::endl; bool done = false; for ( int64_t di = -d+1; di <= d-1; ++di ) { int64_t const apos = std::max( di,static_cast<int64_t>(0))+DP[di].offset; int64_t const bpos = std::max(-di,static_cast<int64_t>(0))+DP[di].offset; assert ( apos >= 0 ); assert ( bpos >= 0 ); assert ( static_cast< uint64_t >(apos) <= an ); assert ( static_cast< uint64_t >(bpos) <= bn ); // std::cerr << "d=" << d << " di=" << di << " apos=" << apos << " bpos=" << bpos << " an=" << an << " bn=" << bn << std::endl; if ( static_cast< uint64_t >(apos) == an || static_cast< uint64_t >(bpos) == bn ) { fdiag = di; done = true; } } if ( done ) { break; } iter_a aa = a; iter_b bb = b + d; { // extend below index_type const p = DP[-d+1].offset; index_type const s = slide<iter_a,iter_b,true>(aa,ae,bb,be,p); DN[-d].offset = p + s; bb -= 1; } { index_type const top = DP[-d+2].offset; index_type const diag = DP[-d+1].offset; if ( diag+1 >= top ) { index_type const p = diag+1; index_type const s = slide<iter_a,iter_b,true>(aa,ae,bb,be,p); DN[-d+1].offset = p + s; } else { index_type const p = top; index_type const s = slide<iter_a,iter_b,true>(aa,ae,bb,be,p); DN[-d+1].offset = p + s; } bb -= 1; } for ( index_type di = -d+2; di < 0; ++di ) { index_type const left = DP[di-1].offset; index_type const diag = DP[di].offset; index_type const top = DP[di+1].offset; if ( diag >= left ) { if ( diag+1 >= top ) { index_type const p = diag+1; index_type const s = slide<iter_a,iter_b,true>(aa,ae,bb,be,p); DN[di].offset = p + s; } else { index_type const p = top; index_type const s = slide<iter_a,iter_b,true>(aa,ae,bb,be,p); DN[di].offset = p + s; } } else { if ( left+1 >= top ) { index_type const p = left+1; index_type const s = slide<iter_a,iter_b,true>(aa,ae,bb,be,p); DN[di].offset = p + s; } else { index_type const p = top; index_type const s = slide<iter_a,iter_b,true>(aa,ae,bb,be,p); DN[di].offset = p + s; } } bb -= 1; } { index_type const left = DP[-1].offset; index_type const diag = DP[0].offset; index_type const top = DP[1].offset; if ( diag >= left ) { if ( diag >= top ) { index_type const p = diag+1; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[0].offset = p + s; } else { index_type const p = top+1; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[0].offset = p + s; } } else { if ( left >= top ) { index_type const p = left+1; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[0].offset = p + s; } else { index_type const p = top+1; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[0].offset = p + s; } } aa += 1; } for ( index_type di = 1; di <= d-2 ; ++di ) { index_type const left = DP[di-1].offset; index_type const diag = DP[di].offset; index_type const top = DP[di+1].offset; if ( diag+1 >= left ) { if ( diag >= top ) { index_type const p = diag+1; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[di].offset = p + s; } else { index_type const p = top+1; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[di].offset = p + s; } } else { if ( left >= top+1 ) { index_type const p = left; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[di].offset = p + s; } else { index_type const p = top+1; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[di].offset = p + s; } } aa += 1; } { index_type const left = DP[d-2].offset; index_type const diag = DP[d-1].offset; if ( diag+1 >= left ) { index_type const p = diag+1; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[ d-1].offset = p + s; } else { index_type const p = left; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[ d-1].offset = p + s; } aa += 1; } { // extend above index_type const p = DP[ d-1].offset; index_type const s = slide<iter_a,iter_b,false>(aa,ae,bb,be,p); DN[d ].offset = p + s; } std::swap(DP,DN); } index_type const ed = d-1; int64_t const apos = std::max( fdiag,static_cast<int64_t>(0))+DP[fdiag].offset; int64_t const bpos = std::max(-fdiag,static_cast<int64_t>(0))+DP[fdiag].offset; assert ( apos >= 0 ); assert ( bpos >= 0 ); return ReturnValue(apos,bpos,ed); }
bool clipAdapters( libmaus2::bambam::BamAlignment & algn, libmaus2::autoarray::AutoArray<char> & R, libmaus2::autoarray::AutoArray<char> & Q, libmaus2::bambam::BamSeqEncodeTable const & seqenc, libmaus2::autoarray::AutoArray<libmaus2::bambam::cigar_operation> & cigop, libmaus2::bambam::BamAlignment::D_array_type & T ) { // a3,as uint64_t const asclip = algn.hasAux("as") ? algn.getAuxAsNumber<int>("as") : 0; uint64_t const a3clip = algn.hasAux("a3") ? algn.getAuxAsNumber<int>("a3") : 0; uint64_t const aclip = std::max(asclip,a3clip); bool const reverse = algn.isReverse(); if ( aclip ) { uint64_t const len = algn.decodeRead(R); algn.decodeQual(Q); if ( (len - aclip) > 1 ) { if ( algn.isMapped() ) { uint32_t const numcigop = algn.getCigarOperations(cigop); if ( numcigop == cigop.size() ) cigop.resize(numcigop+1); if ( reverse ) { std::reverse(cigop.begin(),cigop.begin()+numcigop); } // can't just add a HC to the cigar uint32_t index; uint32_t hardclip = 0; uint32_t cig_type; int32_t left = aclip; int32_t repos = 0; for ( index = numcigop - 1; index > 0; index-- ) { cig_type = bam_cigar_type(cigop[index].first); if ( cig_type == 0 ) { hardclip += cigop[index].second; } else { if ( cig_type & 1 ) { if ( cigop[index].second < left ) { left -= cigop[index].second; } else { break; } } if ( cig_type & 2 ) { // move pos if reversed repos += cigop[index].second; } } } cig_type = bam_cigar_type(cigop[index].first); if ( cigop[index].second != left ) { cigop[index++].second -= left; } cigop[index] = libmaus2::bambam::cigar_operation(libmaus2::bambam::BamFlagBase::LIBMAUS2_BAMBAM_CHARD_CLIP, aclip + hardclip); if ( numcigop > index + 1 ) cigop.resize(index + 1); if ( reverse ) { std::reverse(cigop.begin(),cigop.begin() + index + 1); // account for the last possible pos move if ( cig_type & 2 ) repos += left; if ( repos ) { // clipping has moved the pos point algn.putPos(algn.getPos() + repos); } } algn.replaceCigarString(cigop.begin(),index + 1,T); } if ( !reverse ) { algn.replaceSequence(seqenc,R.begin(),Q.begin(),len-aclip,T); algn.putAuxString("qs",std::string(R.begin()+(len-aclip),R.begin()+len)); algn.putAuxString("qq",std::string(Q.begin()+(len-aclip),Q.begin()+len)); } else { algn.replaceSequence(seqenc, (R.begin() + aclip), (Q.begin() + aclip), len - aclip, T); algn.putAuxString("qs", std::string(R.begin(), R.begin() + aclip)); algn.putAuxString("qq", std::string(Q.begin(), Q.begin() + aclip)); } } } return true; }
void resize(uint64_t const n) { requests.resize(n); }