#include #include #define MIN(a,b) ((a)<(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b)) /* This version receives the second sequence reverse-complemented and * the second quality vector reversed. Allows for a forward loop, * doesn't need the lookup table. */ int prim_match_reads( int i1 // matches from i2 , int i2 // ??? , int r // length to match , const uint8_t *rd1 , const uint8_t *qs1 , const uint8_t *rc_rd2 , const uint8_t *rv_qs2 ) { int acc = 0 ; while( r != 0 ) { uint8_t n1 = rd1[ i1 ] ; uint8_t n2 = rc_rd2[ i2 ] ; uint8_t q1 = qs1[ i1 ] ; uint8_t q2 = rv_qs2[ i2 ] ; acc += (n1 & 0xF) == (n2 & 0xF) ? 0 : 5 + (q1 < q2 ? q1 : q2) ; ++i1 ; ++i2 ; --r ; } return acc ; } int prim_match_ad( int off , int i , const uint8_t *rd , const uint8_t *qs , const uint8_t *ad ) { int acc = 0 ; while( i > 0 ) { --i; acc += rd[ i+off ] == ad[ i ] ? 0 : 5 + (qs[ i+off ] < 25 ? qs[ i+off ] : 25) ; } return acc ; } // return the length that minimizes the score int prim_merge_score ( uint8_t **p_fwd_ads, int *p_fwd_lns, int n_fwd_adapters, uint8_t **p_rev_ads, int *p_rev_lns, int n_rev_adapters, uint8_t *p_rd1, uint8_t *p_qs1, int l1, uint8_t *p_rd2, uint8_t *p_qs2, int l2, uint8_t *p_rrd2, uint8_t *p_rqs2, int *scores ) { int minl = -1 ; int min0 = 6 * (l1+l2) ; int min1= INT_MAX ; for( int l = 0 ; l <= l1+l2 ; ++l ) { int ff = INT_MAX ; for( int i = 0 ; i != n_fwd_adapters ; ++i ) { int efflength = MIN(l1 - l, p_fwd_lns[i]) ; int x = prim_match_ad( l, efflength, p_rd1, p_qs1, p_fwd_ads[i] ) ; ff = MIN(ff, x + 6 * MAX( 0, l1 - p_fwd_lns[i] - l)) ; } int rr = INT_MAX ; for( int i = 0 ; i != n_rev_adapters ; ++i ) { int efflength = MIN(l2 - l,p_rev_lns[i]) ; int x = prim_match_ad( l, efflength, p_rd2, p_qs2, p_rev_ads[i] ) ; rr = MIN(rr, x + 6 * MAX( 0, l1 - p_rev_lns[i] - l)) ; } int minidx1 = MAX(l - l2, 0) ; // vec1, forward int minidx2 = MAX(l2 - l, 0) ; // vec2, forward-on-reverse int efflength = MIN(l1 + l2 - l, l) ; // effective length int mm = efflength <= 0 ? 0 : prim_match_reads( minidx1, minidx2, efflength, p_rd1, p_qs1, p_rrd2, p_rqs2 ) ; int z = 6 * l + ff + rr + mm ; if( z < min0 ) { min1 = min0 ; min0 = z ; minl = l ; } else if( z < min1 ) { min1 = z ; } } scores[0] = min1 - min0 ; scores[1] = 6*(l1+l2) - min0 ; return minl ; }