@@ -40,13 +40,13 @@ impl Alignmentfilters {
4040 let _mifl = minfraglen. unwrap_or ( 0 ) ;
4141 let _mafl = maxfraglen. unwrap_or ( 0 ) ;
4242 let _mnase = mnase. unwrap_or ( false ) ;
43- let _offset = offset. unwrap_or ( ( 1 , - 1 ) ) ;
43+ let _offset = offset. unwrap_or ( ( 0 , 0 ) ) ;
4444 let _frs = filterrnastrand. unwrap_or ( String :: from ( "None" ) ) ;
4545 let _extend = extendreads. unwrap_or ( 0 ) ;
4646 let _center = centerreads. unwrap_or ( false ) ;
4747
4848 // Set the manipulate bool for a quick escape in case manipulation is not needed.
49- if _offset != ( 1 , - 1 ) || _mnase || _extend > 0 || _center {
49+ if _offset != ( 0 , 0 ) || _mnase || _extend > 0 || _center {
5050 manipulate = true ;
5151 }
5252
@@ -144,7 +144,7 @@ impl Alignmentfilters {
144144 }
145145 }
146146
147- pub fn manipulate_record ( & self , rec : & Record ) -> Option < [ u32 ; 2 ] > {
147+ pub fn manipulate_record ( & self , rec : & Record ) -> Option < Vec < u32 > > {
148148 // Not just simple yes - no filtering, but actually manipulating the record.
149149 // In general, this is the case for MNase mode, offset, extendreads and centerreads.
150150 if self . mnase {
@@ -154,26 +154,65 @@ impl Alignmentfilters {
154154 let rinsertsize = rec. insert_size ( ) . abs ( ) as u32 ;
155155 if rec. is_proper_pair ( ) && !rec. is_reverse ( ) && rinsertsize > 1 {
156156 // Not sure why the insert size test is here, but note we always filter prior to manipulating.
157- // insertsize even
158157 let recpos: u32 = rec. pos ( ) as u32 ;
159158 let frag_start = recpos - 1 + rinsertsize / 2 ;
160159
161160 if rinsertsize % 2 == 0 {
162- //
163161 return Some (
164- [ frag_start, frag_start + 2 ]
162+ ( frag_start.. frag_start + 2 ) . collect ( )
165163 ) ;
166164 } else {
167- // Uneven middle, frag start + 4 to keep output consistent with deeptools 3.
168165 return Some (
169- [ frag_start, frag_start + 4 ]
166+ ( frag_start.. frag_start+ 4 ) . collect ( )
170167 ) ;
171168 }
172169 }
173170 return None ;
174171 }
175- if self . offset != ( 1 , -1 ) {
176- println ! ( "Offset implementation" ) ;
172+ if self . offset != ( 0 , 0 ) {
173+ // Collect blocks and flatten them out.
174+ let mut blockvec: Vec < u32 > = rec
175+ . aligned_blocks ( )
176+ . flat_map ( |x| x[ 0 ] as u32 ..x[ 1 ] as u32 )
177+ . collect ( ) ;
178+ let blocklen = blockvec. len ( ) as i32 ;
179+
180+ // Convert potential negative indices to positive indices
181+ // It could be that for the offset only one value is given, in which case we only use that site
182+ if self . offset . 1 == 0 {
183+ //
184+ let pos = if self . offset . 0 < 0 { blocklen + self . offset . 0 } else { self . offset . 0 - 1 } ;
185+ if pos < 0 || pos >= blocklen {
186+ return None ;
187+ }
188+
189+ if rec. is_reverse ( ) {
190+ blockvec. reverse ( ) ;
191+ blockvec = blockvec[ pos as usize ..pos as usize + 1 ] . to_vec ( ) ;
192+ blockvec. reverse ( ) ;
193+ return Some ( blockvec) ;
194+ } else {
195+ blockvec = blockvec[ pos as usize ..pos as usize + 1 ] . to_vec ( ) ;
196+ return Some ( blockvec) ;
197+ }
198+ } else {
199+ let start = if self . offset . 0 < 0 { blocklen + self . offset . 0 } else { self . offset . 0 -1 } ;
200+ let end = if self . offset . 1 < 0 { blocklen + self . offset . 1 + 1 } else { self . offset . 1 } ;
201+
202+ // if the range falls outside the vec, return none (retain deeptools 3 behavior)
203+ if start < 0 || end < 0 || start >= blocklen || end >= blocklen || start >= end {
204+ return None ;
205+ }
206+ if rec. is_reverse ( ) {
207+ blockvec. reverse ( ) ;
208+ blockvec = blockvec[ start as usize ..end as usize ] . to_vec ( ) ;
209+ blockvec. reverse ( ) ;
210+ return Some ( blockvec) ;
211+ } else {
212+ blockvec = blockvec[ start as usize ..end as usize ] . to_vec ( ) ;
213+ return Some ( blockvec) ;
214+ }
215+ }
177216 }
178217 if self . extendreads > 0 {
179218 println ! ( "extendreads implementation" ) ;
0 commit comments