@@ -22,6 +22,10 @@ impl Filter {
22
22
return Ok ( Some ( Event :: Unmapped ) ) ;
23
23
}
24
24
25
+ if !is_unique_record ( record) ? {
26
+ return Ok ( Some ( Event :: Nonunique ) ) ;
27
+ }
28
+
25
29
if let Some ( mapping_quality) = record. mapping_quality ( ) {
26
30
if mapping_quality < self . min_mapping_quality {
27
31
return Ok ( Some ( Event :: LowQuality ) ) ;
@@ -31,3 +35,74 @@ impl Filter {
31
35
Ok ( None )
32
36
}
33
37
}
38
+
39
+ fn is_unique_record ( record : & bam:: Record ) -> io:: Result < bool > {
40
+ use noodles:: sam:: alignment:: record:: data:: field:: Tag ;
41
+
42
+ let data = record. data ( ) ;
43
+
44
+ let Some ( value) = data. get ( & Tag :: ALIGNMENT_HIT_COUNT ) . transpose ( ) ? else {
45
+ return Ok ( false ) ;
46
+ } ;
47
+
48
+ match value. as_int ( ) {
49
+ Some ( n) => Ok ( n == 1 ) , // TODO: `n` == 0.
50
+ None => Err ( io:: Error :: new (
51
+ io:: ErrorKind :: InvalidData ,
52
+ format ! (
53
+ "invalid {:?} field value type: expected an integer, got {:?}" ,
54
+ Tag :: ALIGNMENT_HIT_COUNT ,
55
+ value. ty( ) ,
56
+ ) ,
57
+ ) ) ,
58
+ }
59
+ }
60
+
61
+ #[ cfg( test) ]
62
+ mod tests {
63
+ use noodles:: sam:: {
64
+ self ,
65
+ alignment:: { io:: Write , record:: data:: field:: Tag , record_buf:: data:: field:: Value } ,
66
+ } ;
67
+
68
+ use super :: * ;
69
+
70
+ #[ test]
71
+ fn test_is_unique_record ( ) -> io:: Result < ( ) > {
72
+ fn build_record ( alignment_hit_count : Value ) -> io:: Result < bam:: Record > {
73
+ let header = sam:: Header :: default ( ) ;
74
+
75
+ let record_buf = sam:: alignment:: RecordBuf :: builder ( )
76
+ . set_data (
77
+ [ ( Tag :: ALIGNMENT_HIT_COUNT , alignment_hit_count) ]
78
+ . into_iter ( )
79
+ . collect ( ) ,
80
+ )
81
+ . build ( ) ;
82
+
83
+ let mut writer = bam:: io:: Writer :: from ( Vec :: new ( ) ) ;
84
+ writer. write_alignment_record ( & header, & record_buf) ?;
85
+
86
+ let src = writer. into_inner ( ) ;
87
+ let mut reader = bam:: io:: Reader :: from ( & src[ ..] ) ;
88
+ let mut record = bam:: Record :: default ( ) ;
89
+ reader. read_record ( & mut record) ?;
90
+
91
+ Ok ( record)
92
+ }
93
+
94
+ let record = build_record ( Value :: from ( 1 ) ) ?;
95
+ assert ! ( is_unique_record( & record) ?) ;
96
+
97
+ let record = build_record ( Value :: from ( 2 ) ) ?;
98
+ assert ! ( !is_unique_record( & record) ?) ;
99
+
100
+ let record = build_record ( Value :: from ( "atlas" ) ) ?;
101
+ assert ! ( matches!(
102
+ is_unique_record( & record) ,
103
+ Err ( e) if e. kind( ) == io:: ErrorKind :: InvalidData
104
+ ) ) ;
105
+
106
+ Ok ( ( ) )
107
+ }
108
+ }
0 commit comments