1 /* ===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 */
25
26 #include <ngs-bam/ngs-bam.hpp>
27 #include "bam.hpp"
28
29 #include <ngs/ReadCollection.hpp>
30 #include <ngs/adapter/ReadCollectionItf.hpp>
31 #include <ngs/adapter/AlignmentItf.hpp>
32 #include <ngs/adapter/ReferenceItf.hpp>
33 #include <ngs/adapter/StringItf.hpp>
34
35 class ReadCollection : public ngs_adapt::ReadCollectionItf
36 {
37 class Alignment;
38 class AlignmentNone;
39 class AlignmentSlice;
40 class Reference;
41
42 BAMFile file;
43 std::string const path; /* path used to open the BAM file */
44 public:
ReadCollection(std::string const & filepath)45 ReadCollection(std::string const &filepath)
46 : path(filepath)
47 , file(filepath)
48 {};
49
50 ngs_adapt::StringItf *getName() const;
51 ngs_adapt::ReadGroupItf *getReadGroups() const;
52 bool hasReadGroup(char const spec[]) const;
53 ngs_adapt::ReadGroupItf *getReadGroup(char const spec[]) const;
54 ngs_adapt::ReferenceItf *getReferences() const;
55 bool hasReference(char const spec[]) const;
56 ngs_adapt::ReferenceItf *getReference(char const spec[]) const;
57 ngs_adapt::AlignmentItf *getAlignment(char const spec[]) const;
58 ngs_adapt::AlignmentItf *getAlignments(bool const want_primary,
59 bool const want_secondary) const;
60 uint64_t getAlignmentCount(bool const want_primary,
61 bool const want_secondary) const;
62 ngs_adapt::AlignmentItf *getAlignmentRange(uint64_t const first,
63 uint64_t const count,
64 bool const want_primary,
65 bool const want_secondary ) const;
66 uint64_t getReadCount(bool const want_full,
67 bool const want_partial,
68 bool const want_unaligned) const;
69 ngs_adapt::ReadItf *getRead(char const spec[]) const;
70 ngs_adapt::ReadItf *getReads(bool const want_full,
71 bool const want_partial,
72 bool const want_unaligned) const;
73 ngs_adapt::ReadItf *getReadRange(uint64_t const first,
74 uint64_t const count,
75 bool const want_full,
76 bool const want_partial,
77 bool const want_unaligned) const;
78
Seek(BAMFilePosType const new_pos)79 void Seek(BAMFilePosType const new_pos) {
80 file.Seek(new_pos.fpos(), new_pos.bpos());
81 }
ReadBAMRecord()82 BAMRecord const *ReadBAMRecord() {
83 return file.Read();
84 }
getRefInfo(unsigned const i) const85 HeaderRefInfo const &getRefInfo(unsigned const i) const {
86 return file.getRefInfo(i);
87 }
88 };
89
90 // base class for the Alignment types
91 // defines the default behavior of the Alignment types
92 // by design, this class doesn't actually do anything but throw errors
93 // it is the type that is returned when there can't be any alignments
94 // for example, if want_primary and want_secondary are both false
95 class ReadCollection::AlignmentNone : public ngs_adapt::AlignmentItf
96 {
getCigar(bool const clipped,char const OPCODE[]) const97 virtual ngs_adapt::StringItf *getCigar(bool const clipped, char const OPCODE[]) const {
98 throw std::runtime_error("no rows");
99 }
100 public:
getFragmentId() const101 ngs_adapt::StringItf *getFragmentId() const {
102 throw std::runtime_error("not available");
103 }
getFragmentBases(uint64_t offset,uint64_t length) const104 ngs_adapt::StringItf *getFragmentBases(uint64_t offset, uint64_t length) const {
105 throw std::runtime_error("no rows");
106 }
getFragmentQualities(uint64_t offset,uint64_t length) const107 ngs_adapt::StringItf *getFragmentQualities(uint64_t offset, uint64_t length) const {
108 throw std::runtime_error("no rows");
109 }
getAlignmentId() const110 ngs_adapt::StringItf *getAlignmentId() const {
111 throw std::runtime_error("not available");
112 }
getReferenceSpec() const113 ngs_adapt::StringItf *getReferenceSpec() const {
114 throw std::runtime_error("no rows");
115 }
getMappingQuality() const116 int32_t getMappingQuality() const {
117 throw std::runtime_error("no rows");
118 }
getReferenceBases() const119 ngs_adapt::StringItf *getReferenceBases() const {
120 throw std::runtime_error("not available");
121 }
getReadGroup() const122 ngs_adapt::StringItf *getReadGroup() const {
123 throw std::runtime_error("no rows");
124 }
getReadId() const125 ngs_adapt::StringItf *getReadId() const {
126 throw std::runtime_error("no rows");
127 }
getClippedFragmentBases() const128 ngs_adapt::StringItf *getClippedFragmentBases() const {
129 throw std::runtime_error("not available");
130 }
getClippedFragmentQualities() const131 ngs_adapt::StringItf *getClippedFragmentQualities() const {
132 throw std::runtime_error("not available");
133 }
getAlignedFragmentBases() const134 ngs_adapt::StringItf *getAlignedFragmentBases() const {
135 throw std::runtime_error("not available");
136 }
getAlignedFragmentQualities() const137 ngs_adapt::StringItf *getAlignedFragmentQualities() const {
138 throw std::runtime_error("not available");
139 }
isPrimary() const140 bool isPrimary() const {
141 throw std::runtime_error("no rows");
142 }
getAlignmentPosition() const143 int64_t getAlignmentPosition() const {
144 throw std::runtime_error("no rows");
145 }
getReferencePositionProjectionRange(int64_t ref_pos) const146 uint64_t getReferencePositionProjectionRange ( int64_t ref_pos ) const {
147 throw std::runtime_error("no rows");
148 }
getAlignmentLength() const149 uint64_t getAlignmentLength() const {
150 throw std::runtime_error("no rows");
151 }
getShortCigar(bool clipped) const152 ngs_adapt::StringItf *getShortCigar(bool clipped) const {
153 return getCigar(clipped, "MIDNSHPMM???????");
154 }
getLongCigar(bool clipped) const155 ngs_adapt::StringItf *getLongCigar(bool clipped) const {
156 return getCigar(clipped, "MIDNSHP=X???????");
157 }
getRNAOrientation() const158 char getRNAOrientation () const {
159 throw std::runtime_error("no rows");
160 }
getIsReversedOrientation() const161 bool getIsReversedOrientation() const {
162 throw std::runtime_error("no rows");
163 }
getSoftClip(uint32_t edge) const164 int32_t getSoftClip(uint32_t edge) const {
165 throw std::runtime_error("not available");
166 }
getTemplateLength() const167 uint64_t getTemplateLength() const {
168 throw std::runtime_error("no rows");
169 }
hasMate() const170 bool hasMate() const {
171 throw std::runtime_error("no rows");
172 }
getMateAlignmentId() const173 ngs_adapt::StringItf *getMateAlignmentId() const {
174 throw std::runtime_error("not available");
175 }
getMateAlignment() const176 ngs_adapt::AlignmentItf *getMateAlignment() const {
177 throw std::runtime_error("not available");
178 }
getMateReferenceSpec() const179 ngs_adapt::StringItf *getMateReferenceSpec() const {
180 throw std::runtime_error("no rows");
181 }
getMateIsReversedOrientation() const182 bool getMateIsReversedOrientation() const {
183 throw std::runtime_error("no rows");
184 }
nextAlignment()185 bool nextAlignment() {
186 return false;
187 }
nextFragment()188 bool nextFragment() {
189 throw std::runtime_error("not available");
190 }
191 };
192
193 class ReadCollection::Alignment : public ReadCollection::AlignmentNone
194 {
195 mutable std::string seqBuffer;
196 mutable std::string qualBuffer;
197 mutable std::string cigarBuffer;
198 protected:
199 ReadCollection *parent;
200 BAMRecord const *current;
201 bool want_primary;
202 bool want_secondary;
203
204 ngs_adapt::StringItf *getCigar(bool const clipped, char const OPCODE[]) const;
205
shouldSkip() const206 bool shouldSkip() const {
207 int const flag = current->flag();
208
209 if ((flag & 0x0004) != 0)
210 return true;
211
212 if ((flag & 0x0900) == 0 && !want_primary)
213 return true;
214
215 if ((flag & 0x0900) != 0 && !want_secondary)
216 return true;
217
218 return false;
219 }
220
221 public:
Alignment(ReadCollection const * Parent,bool WantPrimary,bool WantSecondary)222 Alignment(ReadCollection const *Parent, bool WantPrimary, bool WantSecondary) {
223 parent = static_cast<ReadCollection *>(Parent->Duplicate());
224 want_primary = WantPrimary;
225 want_secondary = WantSecondary;
226 current = 0;
227 }
~Alignment()228 virtual ~Alignment() {
229 if (current)
230 delete current;
231 parent->Release();
232 }
233
234 ngs_adapt::StringItf *getFragmentBases(uint64_t offset, uint64_t length) const;
235 ngs_adapt::StringItf *getFragmentQualities(uint64_t offset, uint64_t length) const;
236 ngs_adapt::StringItf *getReferenceSpec() const;
237 int32_t getMappingQuality() const;
238 ngs_adapt::StringItf *getReadGroup() const;
239 ngs_adapt::StringItf *getReadId() const;
240 bool isPrimary() const;
241 int64_t getAlignmentPosition() const;
242 uint64_t getAlignmentLength() const;
243 bool getIsReversedOrientation() const;
244 uint64_t getTemplateLength() const;
245 bool hasMate() const;
246 ngs_adapt::StringItf *getMateReferenceSpec() const;
247 bool getMateIsReversedOrientation() const;
248 bool nextAlignment();
249 };
250
251 class ReadCollection::AlignmentSlice : public ReadCollection::Alignment
252 {
253 unsigned refID;
254 unsigned beg;
255 unsigned end;
256 BAMFilePosTypeList const slice;
257 BAMFilePosTypeList::const_iterator cur;
258 public:
AlignmentSlice(ReadCollection const * Parent,bool const WantPrimary,bool const WantSecondary,BAMFilePosTypeList const & Slice,unsigned const Beg,unsigned const End)259 AlignmentSlice(ReadCollection const *Parent,
260 bool const WantPrimary,
261 bool const WantSecondary,
262 BAMFilePosTypeList const &Slice,
263 unsigned const Beg,
264 unsigned const End)
265 : Alignment(Parent, WantPrimary, WantSecondary)
266 , slice(Slice)
267 , beg(Beg)
268 , end(End)
269 , cur(Slice.begin())
270 {
271 parent->Seek(*cur++);
272 }
273
nextAlignment()274 bool nextAlignment() {
275 for ( ; ; ) {
276 if (!Alignment::nextAlignment())
277 return false;
278 if (current->isSelfMapped()) {
279 unsigned const POS = current->pos();
280 unsigned const REFID = current->refID();
281
282 if (REFID != refID || POS >= end)
283 return false;
284
285 unsigned const REFLEN = current->refLen();
286 if (POS + REFLEN > beg)
287 return true;
288 }
289 }
290 }
291 };
292
293 class ReadCollection::Reference : public ngs_adapt::ReferenceItf
294 {
295 ReadCollection *parent;
296 unsigned cur;
297 unsigned max;
298 int state;
299
300 public:
Reference(ReadCollection const * const Parent,unsigned const current,unsigned const references,int const initState)301 Reference(ReadCollection const *const Parent,
302 unsigned const current,
303 unsigned const references,
304 int const initState)
305 : parent(static_cast<ReadCollection *>(Parent->Duplicate()))
306 , cur(current)
307 , max(references)
308 , state(initState)
309 {}
310
~Reference()311 ~Reference() {
312 parent->Release();
313 }
314
getCommonName() const315 ngs_adapt::StringItf *getCommonName() const {
316 if (state == 2)
317 throw std::runtime_error("no current row");
318
319 HeaderRefInfo const &ri = parent->getRefInfo(cur);
320 std::string const &RNAME = ri.getName();
321
322 return new ngs_adapt::StringItf(RNAME.data(), RNAME.size());
323 }
getCanonicalName() const324 ngs_adapt::StringItf *getCanonicalName() const {
325 throw std::runtime_error("not available");
326 }
327 // TODO: rename to isCircular
getIsCircular() const328 bool getIsCircular() const {
329 throw std::runtime_error("not available");
330 }
getIsLocal() const331 bool getIsLocal () const {
332 throw std::runtime_error("not available");
333 }
getLength() const334 uint64_t getLength() const {
335 if (state == 2)
336 throw std::runtime_error("no current row");
337
338 HeaderRefInfo const &ri = parent->getRefInfo(cur);
339
340 return ri.getLength();
341 }
getReferenceBases(uint64_t const offset,uint64_t const length) const342 ngs_adapt::StringItf *getReferenceBases(uint64_t const offset, uint64_t const length) const {
343 throw std::runtime_error("not available");
344 }
getReferenceChunk(uint64_t const offset,uint64_t const length) const345 ngs_adapt::StringItf *getReferenceChunk(uint64_t const offset, uint64_t const length) const {
346 throw std::runtime_error("not available");
347 }
getAlignmentCount(bool wants_primary,bool wants_secondary) const348 uint64_t getAlignmentCount ( bool wants_primary, bool wants_secondary ) const {
349 throw std::runtime_error("not available");
350 }
getAlignment(char const id[]) const351 ngs_adapt::AlignmentItf *getAlignment(char const id[]) const {
352 throw std::runtime_error("not available");
353 }
getAlignments(bool const want_primary,bool const want_secondary) const354 ngs_adapt::AlignmentItf *getAlignments(bool const want_primary, bool const want_secondary) const {
355 return getAlignmentSlice(0, getLength(), want_primary, want_secondary);
356 }
getAlignmentSlice(int64_t const Start,uint64_t const length,bool const want_primary,bool const want_secondary) const357 ngs_adapt::AlignmentItf *getAlignmentSlice(int64_t const Start, uint64_t const length, bool const want_primary, bool const want_secondary) const {
358 if (state == 2)
359 throw std::runtime_error("no current row");
360
361 HeaderRefInfo const &ri = parent->getRefInfo(cur);
362 unsigned const len = ri.getLength();
363 if (Start >= len)
364 return new ReadCollection::AlignmentNone();
365
366 unsigned const start = Start < 0 ? 0 : Start;
367 uint64_t const End = (Start < 0 ? 0 : Start) + length;
368 unsigned const end = End > len ? len : End;
369 BAMFilePosTypeList const &slice = ri.slice(start, end);
370
371 if (slice.size() == 0)
372 return new ReadCollection::AlignmentNone();
373
374 return new ReadCollection::AlignmentSlice(parent, want_primary, want_secondary,
375 slice, start, end);
376 }
getFilteredAlignmentSlice(int64_t start,uint64_t length,uint32_t flags,int32_t map_qual) const377 ngs_adapt::AlignmentItf * getFilteredAlignmentSlice ( int64_t start, uint64_t length, uint32_t flags, int32_t map_qual ) const {
378 throw std::runtime_error("not available");
379 }
getPileups(bool const want_primary,bool const want_secondary) const380 ngs_adapt::PileupItf *getPileups(bool const want_primary, bool const want_secondary) const {
381 throw std::runtime_error("not available");
382 }
getFilteredPileups(uint32_t flags,int32_t map_qual) const383 ngs_adapt::PileupItf *getFilteredPileups(uint32_t flags, int32_t map_qual) const {
384 throw std::runtime_error("not available");
385 }
getPileupSlice(int64_t const start,uint64_t const length,bool const want_primary,bool const want_secondary) const386 ngs_adapt::PileupItf *getPileupSlice(int64_t const start, uint64_t const length, bool const want_primary, bool const want_secondary) const {
387 throw std::runtime_error("not available");
388 }
getFilteredPileupSlice(int64_t const start,uint64_t const length,uint32_t flags,int32_t map_qual) const389 ngs_adapt::PileupItf *getFilteredPileupSlice(int64_t const start, uint64_t const length, uint32_t flags, int32_t map_qual) const {
390 throw std::runtime_error("not available");
391 }
nextReference()392 bool nextReference() {
393 switch (state) {
394 case 0:
395 if (cur < max) {
396 state = 1;
397 return true;
398 }
399 else {
400 state = 2;
401 return false;
402 }
403 case 1:
404 ++cur;
405 if (cur < max)
406 return true;
407 state = 2;
408 case 2:
409 return false;
410 default:
411 throw std::runtime_error("no more rows available");
412 }
413 }
414 };
415
getName() const416 ngs_adapt::StringItf *ReadCollection::getName() const
417 {
418 unsigned const sep = path.rfind('/');
419
420 if (sep == path.npos)
421 return new ngs_adapt::StringItf(path.data(), path.size());
422 else {
423 char const *name = path.data() + sep + 1;
424 unsigned const len = path.size() - sep - 1;
425 return new ngs_adapt::StringItf(name, len);
426 }
427 }
428
getReadGroups() const429 ngs_adapt::ReadGroupItf *ReadCollection::getReadGroups() const
430 {
431 throw std::logic_error("unimplemented");
432 }
433
hasReadGroup(char const spec[]) const434 bool ReadCollection::hasReadGroup(char const spec[]) const
435 {
436 return false;
437 }
438
getReadGroup(char const spec[]) const439 ngs_adapt::ReadGroupItf *ReadCollection::getReadGroup(char const spec[]) const
440 {
441 throw std::logic_error("unimplemented");
442 }
443
getReferences() const444 ngs_adapt::ReferenceItf *ReadCollection::getReferences() const
445 {
446 return new Reference(this, 0, file.countOfReferences(), 0);
447 }
448
hasReference(char const spec[]) const449 bool ReadCollection::hasReference(char const spec[]) const
450 {
451 int const i = file.getReferenceIndexByName(spec);
452 return i >= 0;
453 }
454
getReference(char const spec[]) const455 ngs_adapt::ReferenceItf *ReadCollection::getReference(char const spec[]) const
456 {
457 int const i = file.getReferenceIndexByName(spec);
458
459 if (i < 0)
460 return NULL;
461 else
462 return new Reference(this, i, 0, 3);
463 }
464
getAlignment(char const spec[]) const465 ngs_adapt::AlignmentItf *ReadCollection::getAlignment(char const spec[]) const
466 {
467 throw std::logic_error("unimplemented");
468 }
469
getAlignments(bool const want_primary,bool const want_secondary) const470 ngs_adapt::AlignmentItf *ReadCollection::getAlignments(bool const want_primary,
471 bool const want_secondary) const
472 {
473 if (!want_secondary && !want_primary)
474 return new AlignmentNone();
475 const_cast<BAMFile *>(&file)->Rewind();
476 return new Alignment(this, want_primary, want_secondary);
477 }
478
getAlignmentCount(bool const want_primary,bool const want_secondary) const479 uint64_t ReadCollection::getAlignmentCount(bool const want_primary,
480 bool const want_secondary) const
481 {
482 throw std::logic_error("unimplemented");
483 }
484
getAlignmentRange(uint64_t const first,uint64_t const count,bool const want_primary,bool const want_secondary) const485 ngs_adapt::AlignmentItf *ReadCollection::getAlignmentRange(uint64_t const first,
486 uint64_t const count,
487 bool const want_primary,
488 bool const want_secondary ) const
489 {
490 throw std::logic_error("unimplemented");
491 }
492
getReadCount(bool const want_full,bool const want_partial,bool const want_unaligned) const493 uint64_t ReadCollection::getReadCount(bool const want_full,
494 bool const want_partial,
495 bool const want_unaligned) const
496 {
497 throw std::logic_error("unimplemented");
498 }
499
getRead(char const spec[]) const500 ngs_adapt::ReadItf *ReadCollection::getRead(char const spec[]) const
501 {
502 throw std::logic_error("unimplemented");
503 }
504
getReads(bool const want_full,bool const want_partial,bool const want_unaligned) const505 ngs_adapt::ReadItf *ReadCollection::getReads(bool const want_full,
506 bool const want_partial,
507 bool const want_unaligned) const
508 {
509 throw std::logic_error("unimplemented");
510 }
511
getReadRange(uint64_t const first,uint64_t const count,bool const want_full,bool const want_partial,bool const want_unaligned) const512 ngs_adapt::ReadItf *ReadCollection::getReadRange(uint64_t const first,
513 uint64_t const count,
514 bool const want_full,
515 bool const want_partial,
516 bool const want_unaligned) const
517 {
518 throw std::logic_error("unimplemented");
519 }
520
getFragmentBases(uint64_t const Offset,uint64_t const Length) const521 ngs_adapt::StringItf *ReadCollection::Alignment::getFragmentBases(uint64_t const Offset, uint64_t const Length) const
522 {
523 uint64_t const End = Offset + Length;
524 unsigned const seqLen = current->l_seq();
525 unsigned const offset = Offset < seqLen ? Offset : seqLen;
526 unsigned const seqEnd = End < seqLen ? End : seqLen;
527
528 seqBuffer.resize(0);
529 seqBuffer.reserve(seqLen);
530
531 for (unsigned i = offset; i < seqEnd; ++i)
532 seqBuffer.append(1, current->seq(i));
533
534 return new ngs_adapt::StringItf(seqBuffer.data(), seqBuffer.size());
535 }
536
getFragmentQualities(uint64_t const Offset,uint64_t const Length) const537 ngs_adapt::StringItf *ReadCollection::Alignment::getFragmentQualities(uint64_t const Offset, uint64_t const Length) const
538 {
539 uint64_t const End = Offset + Length;
540 unsigned const seqLen = current->l_seq();
541 unsigned const offset = Offset < seqLen ? Offset : seqLen;
542 unsigned const seqEnd = End < seqLen ? End : seqLen;
543 bool notFF = false;
544 uint8_t const *qual = current->qual();
545
546 qualBuffer.resize(0);
547 qualBuffer.reserve(seqLen);
548
549 for (unsigned i = offset; i < seqEnd; ++i) {
550 int const qv = qual[i];
551
552 notFF |= (qv != 0xFF);
553 qualBuffer.append(1, (char)((qv > 63 ? 63 : qv) + 33));
554 }
555 return new ngs_adapt::StringItf(qualBuffer.data(), notFF ? qualBuffer.size() : 0);
556 }
557
getReferenceSpec() const558 ngs_adapt::StringItf *ReadCollection::Alignment::getReferenceSpec() const
559 {
560 int const refID = current->refID();
561 HeaderRefInfo const &ri = parent->getRefInfo(refID);
562 std::string const &RNAME = ri.getName();
563 return new ngs_adapt::StringItf(RNAME.data(), RNAME.size());
564 }
565
getMappingQuality() const566 int32_t ReadCollection::Alignment::getMappingQuality() const
567 {
568 return current->mq();
569 }
570
getReadGroup() const571 ngs_adapt::StringItf *ReadCollection::Alignment::getReadGroup() const
572 {
573 for (BAMRecord::OptionalField::const_iterator i = current->begin(); i != current->end(); ++i) {
574 char const *tag = i->getTag();
575 if (tag[0] == 'R' && tag[1] == 'G' && i->getValueType() == 'Z') {
576 return new ngs_adapt::StringItf(i->getRawValue(), i->getElementSize());
577 }
578 }
579 return NULL;
580 }
581
getReadId() const582 ngs_adapt::StringItf *ReadCollection::Alignment::getReadId() const
583 {
584 char const *const QNAME = current->readname();
585 size_t const len = strnlen(QNAME, current->l_read_name());
586 return new ngs_adapt::StringItf(QNAME, len);
587 }
588
isPrimary() const589 bool ReadCollection::Alignment::isPrimary() const
590 {
591 return (current->flag() & 0x0900) == 0;
592 }
593
getAlignmentPosition() const594 int64_t ReadCollection::Alignment::getAlignmentPosition() const
595 {
596 return current->pos();
597 }
598
getAlignmentLength() const599 uint64_t ReadCollection::Alignment::getAlignmentLength() const {
600 return current->refLen();
601 }
602
getCigar(bool const clipped,char const OPCODE[]) const603 ngs_adapt::StringItf *ReadCollection::Alignment::getCigar(bool const clipped, char const OPCODE[]) const
604 {
605 current->cigarString(cigarBuffer, clipped, OPCODE);
606 return new ngs_adapt::StringItf(cigarBuffer.data(), cigarBuffer.size());
607 }
608
getIsReversedOrientation() const609 bool ReadCollection::Alignment::getIsReversedOrientation() const
610 {
611 return (current->flag() & 0x0010) != 0;
612 }
613
614 // TODO: return type should be int64_t
getTemplateLength() const615 uint64_t ReadCollection::Alignment::getTemplateLength() const
616 {
617 return current->tlen();
618 }
619
hasMate() const620 bool ReadCollection::Alignment::hasMate() const
621 {
622 int const FLAG = current->flag();
623
624 return (FLAG & 0x0001) != 0 && (FLAG & 0x00C0) != 0 && (FLAG & 0x00C0) != 0x00C0;
625 }
626
getMateReferenceSpec() const627 ngs_adapt::StringItf *ReadCollection::Alignment::getMateReferenceSpec() const
628 {
629 int const refID = current->next_refID();
630
631 if (refID < 0)
632 return new ngs_adapt::StringItf("", 0);
633
634 HeaderRefInfo const &ri = parent->getRefInfo(refID);
635 std::string const &RNEXT = ri.getName();
636 return new ngs_adapt::StringItf(RNEXT.data(), RNEXT.size());
637 }
638
639 // TODO: rename to isMateReversedOrientation
getMateIsReversedOrientation() const640 bool ReadCollection::Alignment::getMateIsReversedOrientation() const
641 {
642 return (current->flag() & 0x0020) != 0;
643 }
644
nextAlignment()645 bool ReadCollection::Alignment::nextAlignment()
646 {
647 do {
648 if (current) {
649 delete current;
650 current = 0;
651 }
652 current = parent->ReadBAMRecord();
653 if (!current)
654 return false;
655 } while (shouldSkip());
656 return true;
657 }
658
openReadCollection(std::string const & path)659 ngs::ReadCollection NGS_BAM::openReadCollection(std::string const &path)
660 {
661 ngs_adapt::ReadCollectionItf *const self = new ReadCollection(path);
662 NGS_ReadCollection_v1 *const c_obj = self->Cast();
663 ngs::ReadCollectionItf *const ngs_itf = ngs::ReadCollectionItf::Cast(c_obj);
664
665 return ngs::ReadCollection(ngs_itf);
666 }
667