Skip to content

Commit 548f7d2

Browse files
PackedNSeqVec::push_from_ascii_and_quality
1 parent afec41c commit 548f7d2

1 file changed

Lines changed: 30 additions & 0 deletions

File tree

src/packed_n_seq.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,34 @@ impl PackedNSeqVec {
102102
ambiguous,
103103
}
104104
}
105+
106+
/// Create a mask that is 1 for all non-ACGT bases and for all low-quality bases with quality `<threshold`.
107+
pub fn push_from_ascii_and_quality(&mut self, seq: &[u8], quality: &[u8], threshold: usize) {
108+
let r = self.seq.push_ascii(seq);
109+
let r2 = self.ambiguous.push_ascii(seq);
110+
assert_eq!(r, r2);
111+
112+
assert_eq!(seq.len(), quality.len());
113+
114+
// Low-quality bases are also ambiguous.
115+
let t = b'!' + threshold as u8;
116+
let t_simd = i8x32::splat(t as i8);
117+
118+
let idx = r2.start;
119+
let i = 0;
120+
while idx % 8 != 0 {
121+
self.ambiguous.seq[idx / 8] |= ((quality[i] < t) as u8) << (idx % 8);
122+
}
123+
let quality = &quality[i..];
124+
125+
let ambiguous = self.ambiguous.seq[idx / 8..].as_chunks_mut::<4>().0;
126+
for i in (0..quality.len()).step_by(32) {
127+
let chunk =
128+
i8x32::from(unsafe { std::mem::transmute::<_, i8x32>(read_slice_32(quality, i)) });
129+
130+
let mask = t_simd.cmp_lt(chunk).move_mask() as u32;
131+
let ambi = &mut ambiguous[i / 32];
132+
*ambi = (u32::from_ne_bytes(*ambi) | mask).to_ne_bytes();
133+
}
134+
}
105135
}

0 commit comments

Comments
 (0)