1 // Author: Derek Barnett
2 
3 #include <chrono>
4 #include <cstdint>
5 #include <string>
6 #include <vector>
7 
8 #include <gtest/gtest.h>
9 
10 #include <pbbam/BamRecord.h>
11 #include <pbbam/BamRecordView.h>
12 #include <pbbam/BamTagCodec.h>
13 
14 // clang-format off
15 
16 using namespace PacBio;
17 using namespace PacBio::BAM;
18 
19 using f_data = std::vector<uint16_t>;
20 
21 namespace BamRecordMappingTests {
22 
23 static
MakeRecord(const Position qStart,const Position qEnd,const std::string & seq,const std::string & quals,const std::string & tagBases,const std::string & tagQuals,const f_data & frames)24 BamRecord MakeRecord(const Position qStart,
25                      const Position qEnd,
26                      const std::string& seq,
27                      const std::string& quals,
28                      const std::string& tagBases,
29                      const std::string& tagQuals,
30                      const f_data& frames)
31 {
32     BamRecordImpl impl;
33     impl.SetSequenceAndQualities(seq, quals);
34 
35     TagCollection tags;
36     tags["qs"] = qStart;
37     tags["qe"] = qEnd;
38     tags["ip"] = frames;
39     tags["pw"] = frames;
40     tags["dt"] = tagBases;
41     tags["st"] = tagBases;
42     tags["dq"] = tagQuals;
43     tags["iq"] = tagQuals;
44     tags["mq"] = tagQuals;
45     tags["sq"] = tagQuals;
46     tags["pq"] = tagQuals;
47     tags["pv"] = tagQuals;
48     impl.Tags(tags);
49 
50     return BamRecord(std::move(impl));
51 }
52 
53 } // namespace BamRecordMappingTests
54 
TEST(BamRecordMappingTest,BasicMap)55 TEST(BamRecordMappingTest, BasicMap)
56 {
57     const Position qStart = 500;
58     const Position qEnd   = 510;
59     const std::string seq      = "AACCGTTAGC";
60     const std::string quals    = "?]?]?]?]?*";
61     const std::string tagBases = "AACCGTTAGC";
62     const std::string tagQuals = "?]?]?]?]?*";
63     const f_data frames   = { 10, 10, 20, 20, 30, 40, 40, 10, 30, 20 };
64     const uint8_t mapQual = 80;
65 
66     const std::string seq_rev   = "GCTAACGGTT";
67     const std::string quals_rev = "*?]?]?]?]?";
68     const std::string tagBases_rev = seq_rev;
69     const std::string tagQuals_rev = quals_rev;
70     const f_data frames_rev = { 20, 30, 10, 40, 40, 30, 20, 20, 10, 10 };
71 
72     const std::string s1_cigar = "10=";
73     const std::string s2_cigar = "5=3D5=";
74     const std::string s3_cigar = "4=1D2I2D4=";
75 
76     BamRecord s1 = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
77     BamRecord s2 = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
78     BamRecord s3 = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
79     BamRecord s1_rev = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
80     BamRecord s2_rev = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
81     BamRecord s3_rev = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
82 
83     s1.Map(0, 100, Strand::FORWARD, s1_cigar, mapQual);
84     s2.Map(0, 100, Strand::FORWARD, s2_cigar, mapQual);
85     s3.Map(0, 100, Strand::FORWARD, s3_cigar, mapQual);
86     s1_rev.Map(0, 100, Strand::REVERSE, s1_cigar, mapQual);
87     s2_rev.Map(0, 100, Strand::REVERSE, s2_cigar, mapQual);
88     s3_rev.Map(0, 100, Strand::REVERSE, s3_cigar, mapQual);
89 
90     {   // s1 - FORWARD
91         EXPECT_TRUE(s1.IsMapped());
92         EXPECT_EQ(0, s1.ReferenceId());
93         EXPECT_EQ(Strand::FORWARD, s1.AlignedStrand());
94         EXPECT_EQ(mapQual, s1.MapQuality());
95 
96         EXPECT_EQ(qStart, s1.QueryStart());
97         EXPECT_EQ(qEnd,   s1.QueryEnd());
98         EXPECT_EQ(500, s1.AlignedStart());
99         EXPECT_EQ(510, s1.AlignedEnd());         // 500 + 10=
100         EXPECT_EQ(100, s1.ReferenceStart());
101         EXPECT_EQ(110, s1.ReferenceEnd());       // 100 + 10=
102 
103         const BamRecordView view
104         {
105             s1,
106             Orientation::NATIVE,
107             false,
108             false,
109             PulseBehavior::ALL
110         };
111 
112         EXPECT_EQ(seq,      view.Sequence());
113         EXPECT_EQ(quals,    view.Qualities().Fastq());
114         EXPECT_EQ(tagBases, view.DeletionTags());
115         EXPECT_EQ(tagQuals, view.DeletionQVs().Fastq());
116         EXPECT_EQ(tagQuals, view.LabelQVs().Fastq());
117         EXPECT_EQ(tagQuals, view.AltLabelQVs().Fastq());
118         EXPECT_EQ(frames,   view.IPD().Data());
119     }
120 
121     {   // s1 - REVERSE
122 
123         EXPECT_TRUE(s1_rev.IsMapped());
124         EXPECT_EQ(0, s1_rev.ReferenceId());
125         EXPECT_EQ(Strand::REVERSE, s1_rev.AlignedStrand());
126         EXPECT_EQ(mapQual, s1_rev.MapQuality());
127 
128         EXPECT_EQ(qStart, s1_rev.QueryStart());
129         EXPECT_EQ(qEnd,   s1_rev.QueryEnd());
130         EXPECT_EQ(500, s1_rev.AlignedStart());
131         EXPECT_EQ(510, s1_rev.AlignedEnd());         // 500 + 10=
132         EXPECT_EQ(100, s1_rev.ReferenceStart());
133         EXPECT_EQ(110, s1_rev.ReferenceEnd());       // 100 + 10=
134 
135         // native
136         const BamRecordView nativeView
137         {
138             s1_rev,
139             Orientation::NATIVE,
140             false,
141             false,
142             PulseBehavior::ALL
143         };
144         EXPECT_EQ(seq,      nativeView.Sequence());
145         EXPECT_EQ(quals,    nativeView.Qualities().Fastq());
146         EXPECT_EQ(tagBases, nativeView.DeletionTags());
147         EXPECT_EQ(tagQuals, nativeView.DeletionQVs().Fastq());
148         EXPECT_EQ(tagQuals, nativeView.LabelQVs().Fastq());
149         EXPECT_EQ(tagQuals, nativeView.AltLabelQVs().Fastq());
150         EXPECT_EQ(frames,   nativeView.IPD().Data());
151 
152         // - genomic
153         const BamRecordView genomicView
154         {
155             s1_rev,
156             Orientation::GENOMIC,
157             false,
158             false,
159             PulseBehavior::ALL
160         };
161         EXPECT_EQ(seq_rev,      genomicView.Sequence());
162         EXPECT_EQ(quals_rev,    genomicView.Qualities().Fastq());
163         EXPECT_EQ(tagBases_rev, genomicView.DeletionTags());
164         EXPECT_EQ(tagQuals_rev, genomicView.DeletionQVs().Fastq());
165         EXPECT_EQ(tagQuals_rev, genomicView.LabelQVs().Fastq());
166         EXPECT_EQ(tagQuals_rev, genomicView.AltLabelQVs().Fastq());
167         EXPECT_EQ(frames_rev,   genomicView.IPD().Data());
168     }
169 
170     {   // s2 - FORWARD
171 
172         EXPECT_TRUE(s2.IsMapped());
173         EXPECT_EQ(0, s2.ReferenceId());
174         EXPECT_EQ(Strand::FORWARD, s2.AlignedStrand());
175         EXPECT_EQ(mapQual, s2.MapQuality());
176 
177         EXPECT_EQ(qStart, s2.QueryStart());
178         EXPECT_EQ(qEnd,   s2.QueryEnd());
179         EXPECT_EQ(500, s2.AlignedStart());
180         EXPECT_EQ(510, s2.AlignedEnd());         // 500 + 10=
181         EXPECT_EQ(100, s2.ReferenceStart());
182         EXPECT_EQ(113, s2.ReferenceEnd());      // 100 + 10= + 3D
183 
184         const BamRecordView view
185         {
186             s2,
187             Orientation::NATIVE,
188             false,
189             false,
190             PulseBehavior::ALL
191         };
192 
193         EXPECT_EQ(seq,      view.Sequence());
194         EXPECT_EQ(quals,    view.Qualities().Fastq());
195         EXPECT_EQ(tagBases, view.DeletionTags());
196         EXPECT_EQ(tagQuals, view.DeletionQVs().Fastq());
197         EXPECT_EQ(tagQuals, view.LabelQVs().Fastq());
198         EXPECT_EQ(tagQuals, view.AltLabelQVs().Fastq());
199         EXPECT_EQ(frames,   view.IPD().Data());
200     }
201 
202     {   // s2 - REVERSE
203 
204         EXPECT_TRUE(s2_rev.IsMapped());
205         EXPECT_EQ(0, s2_rev.ReferenceId());
206         EXPECT_EQ(Strand::REVERSE, s2_rev.AlignedStrand());
207         EXPECT_EQ(mapQual, s2_rev.MapQuality());
208 
209         EXPECT_EQ(qStart, s2_rev.QueryStart());
210         EXPECT_EQ(qEnd,   s2_rev.QueryEnd());
211         EXPECT_EQ(500, s2_rev.AlignedStart());
212         EXPECT_EQ(510, s2_rev.AlignedEnd());         // 500 + 10=
213         EXPECT_EQ(100, s2_rev.ReferenceStart());
214         EXPECT_EQ(113, s2_rev.ReferenceEnd());      // 100 + 10= + 3D
215 
216         // - native
217         const BamRecordView nativeView
218         {
219             s2_rev,
220             Orientation::NATIVE,
221             false,
222             false,
223             PulseBehavior::ALL
224         };
225         EXPECT_EQ(seq,      nativeView.Sequence());
226         EXPECT_EQ(quals,    nativeView.Qualities().Fastq());
227         EXPECT_EQ(tagBases, nativeView.DeletionTags());
228         EXPECT_EQ(tagQuals, nativeView.DeletionQVs().Fastq());
229         EXPECT_EQ(tagQuals, nativeView.LabelQVs().Fastq());
230         EXPECT_EQ(tagQuals, nativeView.AltLabelQVs().Fastq());
231         EXPECT_EQ(frames,   nativeView.IPD().Data());
232 
233         // - genomic
234         const BamRecordView genomicView
235         {
236             s2_rev,
237             Orientation::GENOMIC,
238             false,
239             false,
240             PulseBehavior::ALL
241         };
242         EXPECT_EQ(seq_rev,      genomicView.Sequence());
243         EXPECT_EQ(quals_rev,    genomicView.Qualities().Fastq());
244         EXPECT_EQ(tagBases_rev, genomicView.DeletionTags());
245         EXPECT_EQ(tagQuals_rev, genomicView.DeletionQVs().Fastq());
246         EXPECT_EQ(tagQuals_rev, genomicView.LabelQVs().Fastq());
247         EXPECT_EQ(tagQuals_rev, genomicView.AltLabelQVs().Fastq());
248         EXPECT_EQ(frames_rev,   genomicView.IPD().Data());
249     }
250 
251     {   // s3 - FORWARD
252 
253         EXPECT_TRUE(s3.IsMapped());
254         EXPECT_EQ(0, s3.ReferenceId());
255         EXPECT_EQ(Strand::FORWARD, s3.AlignedStrand());
256         EXPECT_EQ(mapQual, s3.MapQuality());
257 
258         EXPECT_EQ(qStart, s3.QueryStart());
259         EXPECT_EQ(qEnd,   s3.QueryEnd());
260         EXPECT_EQ(500, s3.AlignedStart());
261         EXPECT_EQ(510, s3.AlignedEnd());         // 500 + 8= + 2I
262         EXPECT_EQ(100, s3.ReferenceStart());
263         EXPECT_EQ(111, s3.ReferenceEnd());      // 100 + 8= + 3D
264 
265         const BamRecordView view
266         {
267             s3,
268             Orientation::NATIVE,
269             false,
270             false,
271             PulseBehavior::ALL
272         };
273 
274         EXPECT_EQ(seq,      view.Sequence());
275         EXPECT_EQ(quals,    view.Qualities().Fastq());
276         EXPECT_EQ(tagBases, view.DeletionTags());
277         EXPECT_EQ(tagQuals, view.DeletionQVs().Fastq());
278         EXPECT_EQ(tagQuals, view.LabelQVs().Fastq());
279         EXPECT_EQ(tagQuals, view.AltLabelQVs().Fastq());
280         EXPECT_EQ(frames,   view.IPD().Data());
281     }
282 
283     {   // s3 - REVERSE
284 
285         EXPECT_TRUE(s3_rev.IsMapped());
286         EXPECT_EQ(0, s3_rev.ReferenceId());
287         EXPECT_EQ(Strand::REVERSE, s3_rev.AlignedStrand());
288         EXPECT_EQ(mapQual, s3_rev.MapQuality());
289 
290         EXPECT_EQ(qStart, s3_rev.QueryStart());
291         EXPECT_EQ(qEnd,   s3_rev.QueryEnd());
292         EXPECT_EQ(500, s3_rev.AlignedStart());
293         EXPECT_EQ(510, s3_rev.AlignedEnd());         // 500 + 8= + 2I
294         EXPECT_EQ(100, s3_rev.ReferenceStart());
295         EXPECT_EQ(111, s3_rev.ReferenceEnd());      // 100 + 8= + 3D
296 
297         // - native
298         const BamRecordView nativeView
299         {
300             s3_rev,
301             Orientation::NATIVE,
302             false,
303             false,
304             PulseBehavior::ALL
305         };
306         EXPECT_EQ(seq,      nativeView.Sequence());
307         EXPECT_EQ(quals,    nativeView.Qualities().Fastq());
308         EXPECT_EQ(tagBases, nativeView.DeletionTags());
309         EXPECT_EQ(tagQuals, nativeView.DeletionQVs().Fastq());
310         EXPECT_EQ(tagQuals, nativeView.LabelQVs().Fastq());
311         EXPECT_EQ(tagQuals, nativeView.AltLabelQVs().Fastq());
312         EXPECT_EQ(frames,   nativeView.IPD().Data());
313 
314         // - genomic
315         const BamRecordView genomicView
316         {
317             s3_rev,
318             Orientation::GENOMIC,
319             false,
320             false,
321             PulseBehavior::ALL
322         };
323         EXPECT_EQ(seq_rev,      genomicView.Sequence());
324         EXPECT_EQ(quals_rev,    genomicView.Qualities().Fastq());
325         EXPECT_EQ(tagBases_rev, genomicView.DeletionTags());
326         EXPECT_EQ(tagQuals_rev, genomicView.DeletionQVs().Fastq());
327         EXPECT_EQ(tagQuals_rev, genomicView.LabelQVs().Fastq());
328         EXPECT_EQ(tagQuals_rev, genomicView.AltLabelQVs().Fastq());
329         EXPECT_EQ(frames_rev,   genomicView.IPD().Data());
330     }
331 }
332 
TEST(BamRecordMappingTest,SoftClipMapping)333 TEST(BamRecordMappingTest, SoftClipMapping)
334 {
335     const Position qStart = 500;
336     const Position qEnd   = 515;
337     const std::string seq      = "TTAACCGTTAGCAAA";
338     const std::string quals    = "--?]?]?]?]?*+++";
339     const std::string tagBases = "TTAACCGTTAGCAAA";
340     const std::string tagQuals = "--?]?]?]?]?*+++";
341     const f_data frames   = { 40, 40, 10, 10, 20, 20, 30, 40, 40, 10, 30, 20, 10, 10, 10 };
342     const uint8_t mapQual = 80;
343 
344     const std::string clipped_seq   = "AACCGTTAGC";
345     const std::string clipped_quals = "?]?]?]?]?*";
346     const std::string clipped_tagBases   = "AACCGTTAGC";
347     const std::string clipped_tagQuals = "?]?]?]?]?*";
348     const f_data clipped_frames = { 10, 10, 20, 20, 30, 40, 40, 10, 30, 20 };
349 
350     const std::string seq_rev   = "TTTGCTAACGGTTAA";
351     const std::string quals_rev = "+++*?]?]?]?]?--";
352     const std::string tagBases_rev = seq_rev;
353     const std::string tagQuals_rev = quals_rev;
354     const f_data frames_rev = { 10, 10, 10, 20, 30, 10, 40, 40, 30, 20, 20, 10, 10, 40, 40 };
355 
356     const std::string clipped_seq_rev   = "GCTAACGGTT";
357     const std::string clipped_quals_rev = "*?]?]?]?]?";
358     const std::string clipped_tagBases_rev = clipped_seq_rev;
359     const std::string clipped_tagQuals_rev = clipped_quals_rev;
360     const f_data clipped_frames_rev = { 20, 30, 10, 40, 40, 30, 20, 20, 10, 10 };
361 
362     const std::string s1_cigar = "2S10=3S";
363     const std::string s2_cigar = "2S5=3D5=3S";
364     const std::string s3_cigar = "2S4=1D2I2D4=3S";
365 
366     BamRecord s1 = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
367     BamRecord s2 = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
368     BamRecord s3 = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
369     BamRecord s1_rev = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
370     BamRecord s2_rev = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
371     BamRecord s3_rev = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
372 
373     s1.Map(0, 100, Strand::FORWARD, s1_cigar, mapQual);
374     s2.Map(0, 100, Strand::FORWARD, s2_cigar, mapQual);
375     s3.Map(0, 100, Strand::FORWARD, s3_cigar, mapQual);
376     s1_rev.Map(0, 100, Strand::REVERSE, s1_cigar, mapQual);
377     s2_rev.Map(0, 100, Strand::REVERSE, s2_cigar, mapQual);
378     s3_rev.Map(0, 100, Strand::REVERSE, s3_cigar, mapQual);
379 
380     {   // s1 - FORWARD
381 
382         EXPECT_TRUE(s1.IsMapped());
383         EXPECT_EQ(0, s1.ReferenceId());
384         EXPECT_EQ(Strand::FORWARD, s1.AlignedStrand());
385         EXPECT_EQ(mapQual, s1.MapQuality());
386 
387         EXPECT_EQ(qStart, s1.QueryStart());      // 500
388         EXPECT_EQ(qEnd,   s1.QueryEnd());        // QStart + seqLength
389         EXPECT_EQ(502, s1.AlignedStart());       // QStart + 2S
390         EXPECT_EQ(512, s1.AlignedEnd());         // AStart + 10=
391         EXPECT_EQ(100, s1.ReferenceStart());     // 100
392         EXPECT_EQ(110, s1.ReferenceEnd());       // RefStart + 10=
393 
394         const BamRecordView view
395         {
396             s1,
397             Orientation::NATIVE,
398             false,
399             false,
400             PulseBehavior::ALL
401         };
402 
403         EXPECT_EQ(seq,      view.Sequence());
404         EXPECT_EQ(quals,    view.Qualities().Fastq());
405         EXPECT_EQ(tagBases, view.DeletionTags());
406         EXPECT_EQ(tagQuals, view.DeletionQVs().Fastq());
407         EXPECT_EQ(tagQuals, view.LabelQVs().Fastq());
408         EXPECT_EQ(tagQuals, view.AltLabelQVs().Fastq());
409         EXPECT_EQ(frames,   view.IPD().Data());
410     }
411 
412     {   // s1 - REVERSE
413 
414         EXPECT_TRUE(s1_rev.IsMapped());
415         EXPECT_EQ(0, s1_rev.ReferenceId());
416         EXPECT_EQ(Strand::REVERSE, s1_rev.AlignedStrand());
417         EXPECT_EQ(mapQual, s1_rev.MapQuality());
418 
419         EXPECT_EQ(qStart, s1_rev.QueryStart());      // 500
420         EXPECT_EQ(qEnd,   s1_rev.QueryEnd());        // QStart + seqLength
421         EXPECT_EQ(503, s1_rev.AlignedStart());       // QStart + 3S
422         EXPECT_EQ(513, s1_rev.AlignedEnd());         // AStart + 10=
423         EXPECT_EQ(100, s1_rev.ReferenceStart());     // 100
424         EXPECT_EQ(110, s1_rev.ReferenceEnd());       // RefStart + 10=
425 
426         // - native
427         const BamRecordView nativeView
428         {
429             s1_rev,
430             Orientation::NATIVE,
431             false,
432             false,
433             PulseBehavior::ALL
434         };
435         EXPECT_EQ(seq,      nativeView.Sequence());
436         EXPECT_EQ(quals,    nativeView.Qualities().Fastq());
437         EXPECT_EQ(tagBases, nativeView.DeletionTags());
438         EXPECT_EQ(tagQuals, nativeView.DeletionQVs().Fastq());
439         EXPECT_EQ(tagQuals, nativeView.LabelQVs().Fastq());
440         EXPECT_EQ(tagQuals, nativeView.AltLabelQVs().Fastq());
441         EXPECT_EQ(frames,   nativeView.IPD().Data());
442 
443         // - genomic
444         const BamRecordView genomicView
445         {
446             s1_rev,
447             Orientation::GENOMIC,
448             false,
449             false,
450             PulseBehavior::ALL
451         };
452         EXPECT_EQ(seq_rev,      genomicView.Sequence());
453         EXPECT_EQ(quals_rev,    genomicView.Qualities().Fastq());
454         EXPECT_EQ(tagBases_rev, genomicView.DeletionTags());
455         EXPECT_EQ(tagQuals_rev, genomicView.DeletionQVs().Fastq());
456         EXPECT_EQ(tagQuals_rev, genomicView.LabelQVs().Fastq());
457         EXPECT_EQ(tagQuals_rev, genomicView.AltLabelQVs().Fastq());
458         EXPECT_EQ(frames_rev,   genomicView.IPD().Data());
459     }
460 
461     {   // s2 - FORWARD
462 
463         EXPECT_TRUE(s2.IsMapped());
464         EXPECT_EQ(0, s2.ReferenceId());
465         EXPECT_EQ(Strand::FORWARD, s2.AlignedStrand());
466         EXPECT_EQ(mapQual, s2.MapQuality());
467 
468         EXPECT_EQ(qStart, s2.QueryStart());      // 500
469         EXPECT_EQ(qEnd,   s2.QueryEnd());        // QStart + seqLength
470         EXPECT_EQ(502, s2.AlignedStart());       // QStart + 2S
471         EXPECT_EQ(512, s2.AlignedEnd());         // AStart + 10=
472         EXPECT_EQ(100, s2.ReferenceStart());     // 100
473         EXPECT_EQ(113, s2.ReferenceEnd());       // RefStart + 10= + 3D
474 
475         const BamRecordView view
476         {
477             s2,
478             Orientation::NATIVE,
479             false,
480             false,
481             PulseBehavior::ALL
482         };
483 
484         EXPECT_EQ(seq,      view.Sequence());
485         EXPECT_EQ(quals,    view.Qualities().Fastq());
486         EXPECT_EQ(tagBases, view.DeletionTags());
487         EXPECT_EQ(tagQuals, view.DeletionQVs().Fastq());
488         EXPECT_EQ(tagQuals, view.LabelQVs().Fastq());
489         EXPECT_EQ(tagQuals, view.AltLabelQVs().Fastq());
490         EXPECT_EQ(frames,   view.IPD().Data());
491     }
492 
493     {   // s2 - REVERSE
494 
495         EXPECT_TRUE(s2_rev.IsMapped());
496         EXPECT_EQ(0, s2_rev.ReferenceId());
497         EXPECT_EQ(Strand::REVERSE, s2_rev.AlignedStrand());
498         EXPECT_EQ(mapQual, s2_rev.MapQuality());
499 
500         EXPECT_EQ(qStart, s2_rev.QueryStart());      // 500
501         EXPECT_EQ(qEnd,   s2_rev.QueryEnd());        // QStart + seqLength
502         EXPECT_EQ(503, s2_rev.AlignedStart());       // QStart + 3S
503         EXPECT_EQ(513, s2_rev.AlignedEnd());         // AStart + 10=
504         EXPECT_EQ(100, s2_rev.ReferenceStart());     // 100
505         EXPECT_EQ(113, s2_rev.ReferenceEnd());       // RefStart + 10= + 3D
506 
507         // - native
508         const BamRecordView nativeView
509         {
510             s2_rev,
511             Orientation::NATIVE,
512             false,
513             false,
514             PulseBehavior::ALL
515         };
516         EXPECT_EQ(seq,      nativeView.Sequence());
517         EXPECT_EQ(quals,    nativeView.Qualities().Fastq());
518         EXPECT_EQ(tagBases, nativeView.DeletionTags());
519         EXPECT_EQ(tagQuals, nativeView.DeletionQVs().Fastq());
520         EXPECT_EQ(tagQuals, nativeView.LabelQVs().Fastq());
521         EXPECT_EQ(tagQuals, nativeView.AltLabelQVs().Fastq());
522         EXPECT_EQ(frames,   nativeView.IPD().Data());
523 
524         // - genomic
525         const BamRecordView genomicView
526         {
527             s2_rev,
528             Orientation::GENOMIC,
529             false,
530             false,
531             PulseBehavior::ALL
532         };
533         EXPECT_EQ(seq_rev,      genomicView.Sequence());
534         EXPECT_EQ(quals_rev,    genomicView.Qualities().Fastq());
535         EXPECT_EQ(tagBases_rev, genomicView.DeletionTags());
536         EXPECT_EQ(tagQuals_rev, genomicView.DeletionQVs().Fastq());
537         EXPECT_EQ(tagQuals_rev, genomicView.LabelQVs().Fastq());
538         EXPECT_EQ(tagQuals_rev, genomicView.AltLabelQVs().Fastq());
539         EXPECT_EQ(frames_rev,   genomicView.IPD().Data());
540     }
541 
542     {   // s3 - FORWARD
543 
544         EXPECT_TRUE(s3.IsMapped());
545         EXPECT_EQ(0, s3.ReferenceId());
546         EXPECT_EQ(Strand::FORWARD, s3.AlignedStrand());
547         EXPECT_EQ(mapQual, s3.MapQuality());
548 
549         EXPECT_EQ(qStart, s3.QueryStart());      // 500
550         EXPECT_EQ(qEnd,   s3.QueryEnd());        // QStart + seqLength
551         EXPECT_EQ(502, s3.AlignedStart());       // QStart + 2S
552         EXPECT_EQ(512, s3.AlignedEnd());         // AStart + 8= + 2I
553         EXPECT_EQ(100, s3.ReferenceStart());     // 100
554         EXPECT_EQ(111, s3.ReferenceEnd());       // RefStart + 8= + 3D
555 
556         const BamRecordView view
557         {
558             s2,
559             Orientation::NATIVE,
560             false,
561             false,
562             PulseBehavior::ALL
563         };
564 
565         EXPECT_EQ(seq,      view.Sequence());
566         EXPECT_EQ(quals,    view.Qualities().Fastq());
567         EXPECT_EQ(tagBases, view.DeletionTags());
568         EXPECT_EQ(tagQuals, view.DeletionQVs().Fastq());
569         EXPECT_EQ(tagQuals, view.LabelQVs().Fastq());
570         EXPECT_EQ(tagQuals, view.AltLabelQVs().Fastq());
571         EXPECT_EQ(frames,   view.IPD().Data());
572     }
573 
574     {   // s3 - REVERSE
575 
576         EXPECT_TRUE(s3_rev.IsMapped());
577         EXPECT_EQ(0, s3_rev.ReferenceId());
578         EXPECT_EQ(Strand::REVERSE, s3_rev.AlignedStrand());
579         EXPECT_EQ(mapQual, s3_rev.MapQuality());
580 
581         EXPECT_EQ(qStart, s3_rev.QueryStart());      // 500
582         EXPECT_EQ(qEnd,   s3_rev.QueryEnd());        // QStart + seqLength
583         EXPECT_EQ(503, s3_rev.AlignedStart());       // QStart + 3S
584         EXPECT_EQ(513, s3_rev.AlignedEnd());         // AStart + 8= + 2I
585         EXPECT_EQ(100, s3_rev.ReferenceStart());     // 100
586         EXPECT_EQ(111, s3_rev.ReferenceEnd());       // RefStart + 8= + 3D
587 
588         // - native
589         const BamRecordView nativeView
590         {
591             s3_rev,
592             Orientation::NATIVE,
593             false,
594             false,
595             PulseBehavior::ALL
596         };
597         EXPECT_EQ(seq,      nativeView.Sequence());
598         EXPECT_EQ(quals,    nativeView.Qualities().Fastq());
599         EXPECT_EQ(tagBases, nativeView.DeletionTags());
600         EXPECT_EQ(tagQuals, nativeView.DeletionQVs().Fastq());
601         EXPECT_EQ(tagQuals, nativeView.LabelQVs().Fastq());
602         EXPECT_EQ(tagQuals, nativeView.AltLabelQVs().Fastq());
603         EXPECT_EQ(frames,   nativeView.IPD().Data());
604 
605         // - genomic
606         const BamRecordView genomicView
607         {
608             s3_rev,
609             Orientation::GENOMIC,
610             false,
611             false,
612             PulseBehavior::ALL
613         };
614         EXPECT_EQ(seq_rev,      genomicView.Sequence());
615         EXPECT_EQ(quals_rev,    genomicView.Qualities().Fastq());
616         EXPECT_EQ(tagBases_rev, genomicView.DeletionTags());
617         EXPECT_EQ(tagQuals_rev, genomicView.DeletionQVs().Fastq());
618         EXPECT_EQ(tagQuals_rev, genomicView.LabelQVs().Fastq());
619         EXPECT_EQ(tagQuals_rev, genomicView.AltLabelQVs().Fastq());
620         EXPECT_EQ(frames_rev,   genomicView.IPD().Data());
621     }
622 }
623 
TEST(BamRecordMappingTest,MappedCopy)624 TEST(BamRecordMappingTest, MappedCopy)
625 {
626     const Position qStart = 500;
627     const Position qEnd   = 510;
628     const std::string seq      = "AACCGTTAGC";
629     const std::string quals    = "?]?]?]?]?*";
630     const std::string tagBases = "AACCGTTAGC";
631     const std::string tagQuals = "?]?]?]?]?*";
632     const f_data frames   = { 10, 10, 20, 20, 30, 40, 40, 10, 30, 20 };
633     const uint8_t mapQual = 80;
634     const std::string cigar    = "4=1D2I2D4=";
635 
636     const BamRecord orig = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
637     const BamRecord mapped = orig.Mapped(0, 100, Strand::FORWARD, cigar, mapQual);
638 
639     EXPECT_TRUE(mapped.IsMapped());
640     EXPECT_EQ(0, mapped.ReferenceId());
641     EXPECT_EQ(Strand::FORWARD, mapped.AlignedStrand());
642     EXPECT_EQ(mapQual, mapped.MapQuality());
643 
644     EXPECT_EQ(500, mapped.QueryStart());      // 500
645     EXPECT_EQ(510, mapped.QueryEnd());        // QStart + seqLength
646     EXPECT_EQ(500, mapped.AlignedStart());    // QStart
647     EXPECT_EQ(510, mapped.AlignedEnd());      // QStart + 8= + 2I
648     EXPECT_EQ(100, mapped.ReferenceStart());  // 100
649     EXPECT_EQ(111, mapped.ReferenceEnd());    // RefStart + 8= + 3D
650 
651     const BamRecordView view
652     {
653         mapped,
654         Orientation::NATIVE,
655         false,
656         false,
657         PulseBehavior::ALL
658     };
659 
660     EXPECT_EQ(seq,      view.Sequence());
661     EXPECT_EQ(quals,    view.Qualities().Fastq());
662     EXPECT_EQ(tagBases, view.DeletionTags());
663     EXPECT_EQ(tagQuals, view.DeletionQVs().Fastq());
664     EXPECT_EQ(tagQuals, view.LabelQVs().Fastq());
665     EXPECT_EQ(tagQuals, view.AltLabelQVs().Fastq());
666     EXPECT_EQ(frames,   view.IPD().Data());
667 }
668 
TEST(BamRecordMappingTest,StaticMapped)669 TEST(BamRecordMappingTest, StaticMapped)
670 {
671     const Position qStart = 500;
672     const Position qEnd   = 510;
673     const std::string seq      = "AACCGTTAGC";
674     const std::string quals    = "?]?]?]?]?*";
675     const std::string tagBases = "AACCGTTAGC";
676     const std::string tagQuals = "?]?]?]?]?*";
677     const f_data frames   = { 10, 10, 20, 20, 30, 40, 40, 10, 30, 20 };
678     const uint8_t mapQual = 80;
679     const std::string cigar    = "4=1D2I2D4=";
680 
681     const BamRecord orig = BamRecordMappingTests::MakeRecord(qStart, qEnd, seq, quals, tagBases, tagQuals, frames);
682     const BamRecord mapped = BamRecord::Mapped(orig, 0, 100, Strand::FORWARD, cigar, mapQual);
683 
684     EXPECT_TRUE(mapped.IsMapped());
685     EXPECT_EQ(0, mapped.ReferenceId());
686     EXPECT_EQ(Strand::FORWARD, mapped.AlignedStrand());
687     EXPECT_EQ(mapQual, mapped.MapQuality());
688 
689     EXPECT_EQ(500, mapped.QueryStart());      // 500
690     EXPECT_EQ(510, mapped.QueryEnd());        // QStart + seqLength
691     EXPECT_EQ(500, mapped.AlignedStart());    // QStart
692     EXPECT_EQ(510, mapped.AlignedEnd());      // QStart + 8= + 2I
693     EXPECT_EQ(100, mapped.ReferenceStart());  // 100
694     EXPECT_EQ(111, mapped.ReferenceEnd());    // RefStart + 8= + 3D
695 
696     const BamRecordView view
697     {
698         mapped,
699         Orientation::NATIVE,
700         false,
701         false,
702         PulseBehavior::ALL
703     };
704 
705     EXPECT_EQ(seq,      view.Sequence());
706     EXPECT_EQ(quals,    view.Qualities().Fastq());
707     EXPECT_EQ(tagBases, view.DeletionTags());
708     EXPECT_EQ(tagQuals, view.DeletionQVs().Fastq());
709     EXPECT_EQ(tagQuals, view.LabelQVs().Fastq());
710     EXPECT_EQ(tagQuals, view.AltLabelQVs().Fastq());
711     EXPECT_EQ(frames,   view.IPD().Data());
712 }
713 
714 // clang-format on
715