44
44
45
45
use super :: ffi as mm_ffi;
46
46
use crate :: { Aligner , Built , Mapping , Strand , BUF } ;
47
+ use minimap2_sys:: { km_destroy, km_init} ;
47
48
use rust_htslib:: bam:: header:: HeaderRecord ;
48
49
use rust_htslib:: bam:: record:: { Cigar , CigarString } ;
49
50
use rust_htslib:: bam:: { Header , HeaderView , Record } ;
@@ -137,11 +138,19 @@ impl Aligner<Built> {
137
138
return Err ( "No index" ) ;
138
139
}
139
140
141
+ // Make sure sequence is not empty
142
+ if seq. is_empty ( ) {
143
+ return Err ( "Sequence is empty" ) ;
144
+ }
145
+
140
146
let query = Query :: new ( seq, qual, name) ;
141
147
// Number of results
142
148
let mut n_regs: i32 = 0 ;
143
149
let mut map_opt = self . mapopt . clone ( ) ;
144
150
151
+ // immutable raw pointer to the index
152
+ let mi = & * * self . idx . as_ref ( ) . unwrap ( ) . as_ref ( ) as * const mm_ffi:: mm_idx_t ;
153
+
145
154
// TODO: other flags to consider:
146
155
// MM_F_NO_PRINT_2ND
147
156
// MM_F_SAM_HIT_ONLY (though this seems to be the default?)
@@ -161,11 +170,9 @@ impl Aligner<Built> {
161
170
}
162
171
163
172
let mappings = BUF . with ( |buf| {
164
- //let km = unsafe { mm_ffi::mm_tbuf_get_km(buf.borrow_mut().buf) };
165
-
166
173
let mm_reg = MaybeUninit :: new ( unsafe {
167
174
mm_ffi:: mm_map (
168
- & * * self . idx . as_ref ( ) . unwrap ( ) . as_ref ( ) as * const mm_ffi :: mm_idx_t ,
175
+ mi ,
169
176
query. inner . l_seq ,
170
177
query. inner . seq as * const libc:: c_char ,
171
178
& mut n_regs,
@@ -186,31 +193,21 @@ impl Aligner<Built> {
186
193
for i in 0 ..n_regs {
187
194
let sam_str = unsafe {
188
195
let mut result: MaybeUninit < mm_ffi:: kstring_t > = MaybeUninit :: zeroed ( ) ;
189
- let reg_ptr = ( * mm_reg. as_ptr ( ) ) . offset ( i as isize ) ;
190
- // // println!("{:#?}", *reg_ptr);
191
- let const_ptr = reg_ptr as * const mm_ffi:: mm_reg1_t ;
192
- // TODO: use mm_write_sam3 t do the writing so that we can pass the map_opt flags
193
- mm_ffi:: mm_write_sam (
196
+ let const_ptr = * mm_reg. as_ptr ( ) as * const mm_ffi:: mm_reg1_t ;
197
+ let km = km_init ( ) ;
198
+ mm_ffi:: mm_write_sam2 (
194
199
result. as_mut_ptr ( ) ,
195
- & * * self . idx . as_ref ( ) . unwrap ( ) . as_ref ( ) as * const mm_ffi :: mm_idx_t ,
200
+ mi ,
196
201
& query. inner as * const mm_ffi:: mm_bseq1_t ,
197
- const_ptr,
198
- n_regs,
199
- * mm_reg. as_ptr ( ) as * const mm_ffi:: mm_reg1_t ,
202
+ 0 ,
203
+ i,
204
+ 1 ,
205
+ & n_regs,
206
+ & const_ptr,
207
+ km,
208
+ map_opt. flag ,
200
209
) ;
201
- //mm_ffi::mm_write_sam3(
202
- // result.as_mut_ptr(),
203
- // self.idx.as_ref().unwrap() as *const mm_ffi::mm_idx_t,
204
- // &read as *const mm_ffi::mm_bseq1_t,
205
- // 0, // seg_idx doesn't apply here (think it's a batch index)
206
- // i,
207
- // 1, // only 1 segment
208
- // n_regs as *const i32,
209
- // &const_ptr,
210
- // km,
211
- // map_opt.flag,
212
- // 0
213
- //);
210
+ km_destroy ( km) ;
214
211
CStr :: from_ptr ( ( * result. as_ptr ( ) ) . s )
215
212
} ;
216
213
let record = Record :: from_sam ( header, sam_str. to_bytes ( ) ) . unwrap ( ) ;
@@ -471,7 +468,11 @@ mod tests {
471
468
( aligner, idx, header_view, expected_recs, seq, qual)
472
469
}
473
470
474
- fn map_test_case ( query_name : & str , spliced : bool ) -> ( Vec < Record > , Vec < Record > ) {
471
+ fn map_test_case (
472
+ query_name : & str ,
473
+ spliced : bool ,
474
+ extra_flags : Option < Vec < u64 > > ,
475
+ ) -> ( Vec < Record > , Vec < Record > ) {
475
476
let ( aligner, _, header_view, expected, seq, qual) = get_test_case ( query_name, spliced) ;
476
477
let observed = aligner
477
478
. map_to_sam (
@@ -480,7 +481,7 @@ mod tests {
480
481
Some ( query_name. as_bytes ( ) ) ,
481
482
& header_view,
482
483
None ,
483
- None ,
484
+ extra_flags ,
484
485
)
485
486
. unwrap ( ) ;
486
487
( observed, expected)
@@ -489,32 +490,48 @@ mod tests {
489
490
#[ test]
490
491
fn test_fwd ( ) {
491
492
let query_name = "perfect_read.fwd" ;
492
- let ( o, e) = map_test_case ( query_name, false ) ;
493
+ let ( o, e) = map_test_case ( query_name, false , None ) ;
493
494
check_single_mapper ( & e, & o) ;
494
495
}
495
496
496
497
#[ test]
497
498
fn test_rev ( ) {
498
499
let query_name = "perfect_read.rev" ;
499
- let ( o, e) = map_test_case ( query_name, false ) ;
500
+ let ( o, e) = map_test_case ( query_name, false , None ) ;
500
501
check_single_mapper ( & e, & o) ;
501
502
}
502
503
503
504
#[ test]
504
505
fn test_mismatch ( ) {
505
506
let query_name = "imperfect_read.fwd" ;
506
- let ( o, e) = map_test_case ( query_name, false ) ;
507
+ let ( o, e) = map_test_case ( query_name, false , None ) ;
507
508
check_single_mapper ( & e, & o) ;
508
509
509
510
let rec = o. first ( ) . unwrap ( ) ;
510
511
let nm = rec. aux ( b"NM" ) . unwrap ( ) ;
511
512
assert_eq ! ( nm, Aux :: U8 ( 5 ) ) ;
512
513
}
513
514
515
+ #[ test]
516
+ fn test_aux_tag ( ) {
517
+ let query_name = "imperfect_read.fwd" ;
518
+ let xtra_flags = vec ! [ mm_ffi:: MM_F_OUT_MD as u64 ] ;
519
+ let ( o, e) = map_test_case ( query_name, false , Some ( xtra_flags) ) ;
520
+ let expected = e. first ( ) . unwrap ( ) ;
521
+ let observed = o. first ( ) . unwrap ( ) ;
522
+ if let ( Ok ( Aux :: String ( e_md) ) , Ok ( Aux :: String ( o_md) ) ) =
523
+ ( expected. aux ( b"MD" ) , observed. aux ( b"MD" ) )
524
+ {
525
+ assert_eq ! ( o_md. as_bytes( ) , e_md. as_bytes( ) )
526
+ } else {
527
+ panic ! ( "Could not read MD tag" ) ;
528
+ }
529
+ }
530
+
514
531
#[ test]
515
532
fn test_unmapped ( ) {
516
533
let query_name = "unmappable_read" ;
517
- let ( o, e) = map_test_case ( query_name, false ) ;
534
+ let ( o, e) = map_test_case ( query_name, false , None ) ;
518
535
check_single_mapper ( & e, & o) ;
519
536
let rec = o. first ( ) . unwrap ( ) ;
520
537
assert ! ( rec. is_unmapped( ) ) ;
@@ -523,7 +540,7 @@ mod tests {
523
540
#[ test]
524
541
fn test_secondary ( ) {
525
542
let query_name = "perfect_inv_duplicate" ;
526
- let ( o, e) = map_test_case ( query_name, false ) ;
543
+ let ( o, e) = map_test_case ( query_name, false , None ) ;
527
544
528
545
assert_eq ! ( o. len( ) , 2 ) ; // expect a primary and secondary mapping
529
546
let o_fields: Vec < _ > = o
@@ -544,7 +561,7 @@ mod tests {
544
561
#[ test]
545
562
fn test_supplementary ( ) {
546
563
let query_name = "split_read" ;
547
- let ( o, e) = map_test_case ( query_name, false ) ;
564
+ let ( o, e) = map_test_case ( query_name, false , None ) ;
548
565
549
566
assert_eq ! ( o. len( ) , 2 ) ; // expect a primary and supplementary mapping
550
567
let o_fields: Vec < _ > = o
@@ -562,7 +579,7 @@ mod tests {
562
579
#[ test]
563
580
fn test_spliced ( ) {
564
581
let query_name = "cdna.fwd" ;
565
- let ( o, e) = map_test_case ( query_name, true ) ;
582
+ let ( o, e) = map_test_case ( query_name, true , None ) ;
566
583
check_single_mapper ( & e, & o) ;
567
584
568
585
let record = o. first ( ) . unwrap ( ) ;
@@ -585,7 +602,7 @@ mod tests {
585
602
#[ test]
586
603
fn test_spliced_rev ( ) {
587
604
let query_name = "cdna.rev" ;
588
- let ( o, e) = map_test_case ( query_name, true ) ;
605
+ let ( o, e) = map_test_case ( query_name, true , None ) ;
589
606
check_single_mapper ( & e, & o) ;
590
607
}
591
608
0 commit comments