From 4db885006cdbadde6c45e59e0169db3f74749a04 Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Thu, 16 Jun 2022 23:06:15 -0600 Subject: [PATCH 01/12] bam::Record:new should return a valid record See #339. --- src/bam/record.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/bam/record.rs b/src/bam/record.rs index 00ae963f0..b2730c6ab 100644 --- a/src/bam/record.rs +++ b/src/bam/record.rs @@ -113,12 +113,19 @@ fn extranul_from_qname(qname: &[u8]) -> usize { impl Record { /// Create an empty BAM record. pub fn new() -> Self { - Record { + let record = Record { inner: unsafe { MaybeUninit::zeroed().assume_init() }, own: true, cigar: None, header: None, } + // Developer note: these are needed so the returned record is properly + // initialized as unmapped. + record.set_tid(-1); + record.set_pos(-1); + record.set_mpos(-1); + record.set_mtid(-1); + record } pub fn from_inner(from: *mut htslib::bam1_t) -> Self { From a3278b94a7ba6d9a494c02e88b1ec90bf11af401 Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Fri, 17 Jun 2022 23:05:26 -0600 Subject: [PATCH 02/12] Update record.rs --- src/bam/record.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bam/record.rs b/src/bam/record.rs index b2730c6ab..16b628d0e 100644 --- a/src/bam/record.rs +++ b/src/bam/record.rs @@ -118,7 +118,7 @@ impl Record { own: true, cigar: None, header: None, - } + }; // Developer note: these are needed so the returned record is properly // initialized as unmapped. record.set_tid(-1); From cf5bf1a6eeefbd7a2440a5682f0d8f23a5d381c4 Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Sat, 18 Jun 2022 07:50:08 -0600 Subject: [PATCH 03/12] Update src/bam/record.rs --- src/bam/record.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bam/record.rs b/src/bam/record.rs index 16b628d0e..3a133a4c5 100644 --- a/src/bam/record.rs +++ b/src/bam/record.rs @@ -113,7 +113,7 @@ fn extranul_from_qname(qname: &[u8]) -> usize { impl Record { /// Create an empty BAM record. pub fn new() -> Self { - let record = Record { + let mut record = Record { inner: unsafe { MaybeUninit::zeroed().assume_init() }, own: true, cigar: None, From cacc1f3ce9372d348d64742b4d735a9b1718fe44 Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Sat, 18 Jun 2022 17:11:48 -0600 Subject: [PATCH 04/12] Update mod.rs --- src/bam/mod.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/bam/mod.rs b/src/bam/mod.rs index 67313dcec..d0dba0f6a 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -2818,4 +2818,59 @@ CCCCCCCCCCCCCCCCCCC"[..], assert_eq!(header_refseqs[0].get("SN").unwrap(), "ref_1",); assert_eq!(header_refseqs[0].get("LN").unwrap(), "10000000",); } + + #[test] + fn test_bam_new() { + // Create the path to write the tmp test BAM + let tmp = tempfile::Builder::new() + .prefix("rust-htslib") + .tempdir() + .expect("Cannot create temp dir"); + let bampath = tmp.path().join("test.bam"); + + // write an unmapped BAM record (uBAM) + { + // Build the header + let mut header = Header::new(); + + // Add the version + header.push_record( + HeaderRecord::new(b"HD") + .push_tag(b"VN", &"1.6") + .push_tag(b"SO", &"unsorted") + ); + + // Build the writer + let mut writer = Writer::from_path(bampath, &header, Format::Bam).unwrap(); + + // Build an empty record + let mut record = BamRecord::new(); + + // By default the read is mapped, so unset it. + record.set_unmapped(); + + // Write the record (this previously seg-faulted) + writer.write(&record); + } + + // Read the record + { + // Build th reader + let mut reader = Reader::from_path(&bampath).expect("Error opening file."); + + // Read the record + let mut rec = record::Record::new(); + match bam.read(&mut rec) { + Some(r) => r.expect("Failed to read record."), + None => {} + }; + + // Check a few things + assert!(rec.is_unmapped()); + assert_eq!(rec.tid(), -1); + assert_eq!(rec.pos(), -1); + assert_eq!(rec.mtid(), -1); + assert_eq!(rec.mpos(), -1); + } + } } From f02c86e5acdb04d5fc0a4d105d31af31a9cb9d97 Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Sat, 18 Jun 2022 17:29:35 -0600 Subject: [PATCH 05/12] fix whitespaces --- src/bam/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bam/mod.rs b/src/bam/mod.rs index d0dba0f6a..556069238 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -2827,7 +2827,7 @@ CCCCCCCCCCCCCCCCCCC"[..], .tempdir() .expect("Cannot create temp dir"); let bampath = tmp.path().join("test.bam"); - + // write an unmapped BAM record (uBAM) { // Build the header @@ -2845,26 +2845,26 @@ CCCCCCCCCCCCCCCCCCC"[..], // Build an empty record let mut record = BamRecord::new(); - + // By default the read is mapped, so unset it. record.set_unmapped(); // Write the record (this previously seg-faulted) writer.write(&record); } - + // Read the record { // Build th reader let mut reader = Reader::from_path(&bampath).expect("Error opening file."); - + // Read the record let mut rec = record::Record::new(); match bam.read(&mut rec) { Some(r) => r.expect("Failed to read record."), None => {} }; - + // Check a few things assert!(rec.is_unmapped()); assert_eq!(rec.tid(), -1); From 7e3fd68c32dd460d8728390927ccbfe62dcff3be Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Sat, 18 Jun 2022 17:40:34 -0600 Subject: [PATCH 06/12] Update mod.rs --- src/bam/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bam/mod.rs b/src/bam/mod.rs index 556069238..c9bfe3521 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -2818,7 +2818,7 @@ CCCCCCCCCCCCCCCCCCC"[..], assert_eq!(header_refseqs[0].get("SN").unwrap(), "ref_1",); assert_eq!(header_refseqs[0].get("LN").unwrap(), "10000000",); } - + #[test] fn test_bam_new() { // Create the path to write the tmp test BAM @@ -2837,11 +2837,11 @@ CCCCCCCCCCCCCCCCCCC"[..], header.push_record( HeaderRecord::new(b"HD") .push_tag(b"VN", &"1.6") - .push_tag(b"SO", &"unsorted") + .push_tag(b"SO", &"unsorted"), ); // Build the writer - let mut writer = Writer::from_path(bampath, &header, Format::Bam).unwrap(); + let mut writer = Writer::from_path(bampath, &header, Format::Bam).unwrap(); // Build an empty record let mut record = BamRecord::new(); @@ -2870,7 +2870,7 @@ CCCCCCCCCCCCCCCCCCC"[..], assert_eq!(rec.tid(), -1); assert_eq!(rec.pos(), -1); assert_eq!(rec.mtid(), -1); - assert_eq!(rec.mpos(), -1); + assert_eq!(rec.mpos(), -1); } } } From 5ddbd6b321df0c5307872401b59a6d7792a917eb Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Sat, 18 Jun 2022 21:03:04 -0600 Subject: [PATCH 07/12] Update mod.rs --- src/bam/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bam/mod.rs b/src/bam/mod.rs index c9bfe3521..1ac610536 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -2844,7 +2844,7 @@ CCCCCCCCCCCCCCCCCCC"[..], let mut writer = Writer::from_path(bampath, &header, Format::Bam).unwrap(); // Build an empty record - let mut record = BamRecord::new(); + let mut record = Record::new(); // By default the read is mapped, so unset it. record.set_unmapped(); @@ -2859,7 +2859,7 @@ CCCCCCCCCCCCCCCCCCC"[..], let mut reader = Reader::from_path(&bampath).expect("Error opening file."); // Read the record - let mut rec = record::Record::new(); + let mut rec = Record::new(); match bam.read(&mut rec) { Some(r) => r.expect("Failed to read record."), None => {} From 1aaad6f48bdb22677e08b1423bafb7ee5004c1e1 Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Sun, 19 Jun 2022 00:46:59 -0600 Subject: [PATCH 08/12] Update src/bam/mod.rs --- src/bam/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bam/mod.rs b/src/bam/mod.rs index 1ac610536..77b99f1b3 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -2860,7 +2860,7 @@ CCCCCCCCCCCCCCCCCCC"[..], // Read the record let mut rec = Record::new(); - match bam.read(&mut rec) { + match reader.read(&mut rec) { Some(r) => r.expect("Failed to read record."), None => {} }; From 2b47d10e2eac6111659a9d6802a2c7cd0601cfb1 Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Wed, 29 Jun 2022 17:16:35 -0600 Subject: [PATCH 09/12] Update src/bam/mod.rs --- src/bam/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bam/mod.rs b/src/bam/mod.rs index 77b99f1b3..59b6dbd38 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -2841,7 +2841,7 @@ CCCCCCCCCCCCCCCCCCC"[..], ); // Build the writer - let mut writer = Writer::from_path(bampath, &header, Format::Bam).unwrap(); + let mut writer = Writer::from_path(&bampath, &header, Format::Bam).unwrap(); // Build an empty record let mut record = Record::new(); From 81013f90f0a1c2ca30f17c5ce7dd7eb80d1fc6dd Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Wed, 29 Jun 2022 22:55:40 -0600 Subject: [PATCH 10/12] fix --- src/bam/mod.rs | 16 ++++++++-------- src/bam/record.rs | 4 ++++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/bam/mod.rs b/src/bam/mod.rs index 59b6dbd38..7012e059f 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -2268,7 +2268,7 @@ CCCCCCCCCCCCCCCCCCC"[..], where F: Fn(&record::Record) -> Option, { - let mut bam_reader = Reader::from_path(bamfile).unwrap(); // internal functions, just unwarp + let mut bam_reader = Reader::from_path(bamfile).unwrap(); // internal functions, just unwrap let header = header::Header::from_template(bam_reader.header()); let mut sam_writer = Writer::from_path(samfile, &header, Format::Sam).unwrap(); for record in bam_reader.records() { @@ -2826,7 +2826,9 @@ CCCCCCCCCCCCCCCCCCC"[..], .prefix("rust-htslib") .tempdir() .expect("Cannot create temp dir"); - let bampath = tmp.path().join("test.bam"); + //let bampath = tmp.path().join("test.bam"); + //let bampath = "/tmp/test.bam"; + let bampath = "/tmp/test.sam"; // write an unmapped BAM record (uBAM) { @@ -2841,16 +2843,14 @@ CCCCCCCCCCCCCCCCCCC"[..], ); // Build the writer - let mut writer = Writer::from_path(&bampath, &header, Format::Bam).unwrap(); + //let mut writer = Writer::from_path(&bampath, &header, Format::Bam).unwrap(); + let mut writer = Writer::from_path(&bampath, &header, Format::Sam).unwrap(); // Build an empty record let mut record = Record::new(); - // By default the read is mapped, so unset it. - record.set_unmapped(); - // Write the record (this previously seg-faulted) - writer.write(&record); + assert!(writer.write(&record).is_ok()); } // Read the record @@ -2862,7 +2862,7 @@ CCCCCCCCCCCCCCCCCCC"[..], let mut rec = Record::new(); match reader.read(&mut rec) { Some(r) => r.expect("Failed to read record."), - None => {} + None => panic!("No record read."), }; // Check a few things diff --git a/src/bam/record.rs b/src/bam/record.rs index 3a133a4c5..13c39e23e 100644 --- a/src/bam/record.rs +++ b/src/bam/record.rs @@ -119,8 +119,12 @@ impl Record { cigar: None, header: None, }; + // The read/query name needs to be set as empty to properly initialize + // the record + record.set_qname(b""); // Developer note: these are needed so the returned record is properly // initialized as unmapped. + record.set_unmapped(); record.set_tid(-1); record.set_pos(-1); record.set_mpos(-1); From 9cd847d33032f5aa0c21a378a2374079a888b243 Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Wed, 29 Jun 2022 22:56:24 -0600 Subject: [PATCH 11/12] fix --- src/bam/mod.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/bam/mod.rs b/src/bam/mod.rs index 7012e059f..0bc71f9c5 100644 --- a/src/bam/mod.rs +++ b/src/bam/mod.rs @@ -2826,9 +2826,7 @@ CCCCCCCCCCCCCCCCCCC"[..], .prefix("rust-htslib") .tempdir() .expect("Cannot create temp dir"); - //let bampath = tmp.path().join("test.bam"); - //let bampath = "/tmp/test.bam"; - let bampath = "/tmp/test.sam"; + let bampath = tmp.path().join("test.bam"); // write an unmapped BAM record (uBAM) { @@ -2843,8 +2841,7 @@ CCCCCCCCCCCCCCCCCCC"[..], ); // Build the writer - //let mut writer = Writer::from_path(&bampath, &header, Format::Bam).unwrap(); - let mut writer = Writer::from_path(&bampath, &header, Format::Sam).unwrap(); + let mut writer = Writer::from_path(&bampath, &header, Format::Bam).unwrap(); // Build an empty record let mut record = Record::new(); From d4bc4929fa1c75094a6576bf2b805e949e90fd2a Mon Sep 17 00:00:00 2001 From: Nils Homer Date: Tue, 21 May 2024 23:42:13 -0700 Subject: [PATCH 12/12] review fixup --- src/bam/record_serde.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bam/record_serde.rs b/src/bam/record_serde.rs index 651867030..1bf8a2fa1 100644 --- a/src/bam/record_serde.rs +++ b/src/bam/record_serde.rs @@ -8,6 +8,8 @@ use serde_bytes::{ByteBuf, Bytes}; use crate::bam::record::Record; fn fix_l_extranul(rec: &mut Record) { + // first, reset the number of extranuls to 0 for calling .qname(); then calculate how many we actually have + rec.inner_mut().core.l_extranul = 0; let l_extranul = rec.qname().iter().rev().take_while(|x| **x == 0u8).count() as u8; rec.inner_mut().core.l_extranul = l_extranul; }