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