]> git.donarmstrong.com Git - bamtools.git/commitdiff
Moved BamReaderPrivate::CalculateAlignmentEnd() to BamAlignment::GetEndPosition(...
authorbarnett <barnett@9efb377e-2e27-44b9-b91a-ec4abb80ed8b>
Wed, 14 Apr 2010 16:32:52 +0000 (16:32 +0000)
committerbarnett <barnett@9efb377e-2e27-44b9-b91a-ec4abb80ed8b>
Wed, 14 Apr 2010 16:32:52 +0000 (16:32 +0000)
git-svn-id: svn+ssh://gene.bc.edu/home/subversion/Derek/BamTools/trunk@49 9efb377e-2e27-44b9-b91a-ec4abb80ed8b

BamAux.h
BamReader.cpp

index 3bb2ce8d94e37e4b3cf0cc572550f0dc62729038..2ce273307b4c52542616c6e12cb88ecedd46b4fb 100644 (file)
--- a/BamAux.h
+++ b/BamAux.h
@@ -3,7 +3,7 @@
 // Marth Lab, Department of Biology, Boston College\r
 // All rights reserved.\r
 // ---------------------------------------------------------------------------\r
-// Last modified: 31 March 2010 (DB)\r
+// Last modified: 14 April 2010 (DB)\r
 // ---------------------------------------------------------------------------\r
 // Provides the basic constants, data structures, etc. for using BAM files\r
 // ***************************************************************************\r
@@ -65,179 +65,53 @@ const int BT_SIZEOF_INT = 4;
 struct CigarOp;\r
 \r
 struct BamAlignment {\r
-\r
-    // Queries against alignment flag\r
-    public:\r
-        // Returns true if this read is a PCR duplicate (determined by external app)\r
-        bool IsDuplicate(void) const { return ( (AlignmentFlag & DUPLICATE) != 0 ); }\r
-        // Returns true if this read failed quality control (determined by external app)\r
-        bool IsFailedQC(void) const { return ( (AlignmentFlag & QC_FAILED) != 0 ); }\r
-        // Returns true if alignment is first mate on read\r
-        bool IsFirstMate(void) const { return ( (AlignmentFlag & READ_1) != 0 ); }\r
-        // Returns true if alignment is mapped\r
-        bool IsMapped(void) const { return ( (AlignmentFlag & UNMAPPED) == 0 ); }\r
-        // Returns true if alignment's mate is mapped\r
-        bool IsMateMapped(void) const { return ( (AlignmentFlag & MATE_UNMAPPED) == 0 ); }\r
-        // Returns true if alignment's mate mapped to reverse strand\r
-        bool IsMateReverseStrand(void) const { return ( (AlignmentFlag & MATE_REVERSE)  != 0 ); }\r
-        // Returns true if alignment part of paired-end read\r
-        bool IsPaired(void) const { return ( (AlignmentFlag & PAIRED) != 0 ); }\r
-        // Returns true if this position is primary alignment (determined by external app)\r
-        bool IsPrimaryAlignment(void) const  { return ( (AlignmentFlag & SECONDARY) == 0 ); }\r
-        // Returns true if alignment is part of read that satisfied paired-end resolution (determined by external app)\r
-        bool IsProperPair(void) const { return ( (AlignmentFlag & PROPER_PAIR) != 0 ); }\r
-        // Returns true if alignment mapped to reverse strand\r
-        bool IsReverseStrand(void) const { return ( (AlignmentFlag & REVERSE) != 0 ); }\r
-        // Returns true if alignment is second mate on read\r
-        bool IsSecondMate(void) const { return ( (AlignmentFlag & READ_2) != 0 ); }\r
-\r
-    // Manipulate alignment flag\r
+
+    // constructors & destructor
+    public:
+        BamAlignment(void);
+        BamAlignment(const BamAlignment& other);
+        ~BamAlignment(void);
+\r
+    // Queries against alignment flags\r
+    public:        \r
+        bool IsDuplicate(void) const;          // Returns true if this read is a PCR duplicate       \r
+        bool IsFailedQC(void) const;           // Returns true if this read failed quality control      \r
+        bool IsFirstMate(void) const;          // Returns true if alignment is first mate on read        \r
+        bool IsMapped(void) const;             // Returns true if alignment is mapped        \r
+        bool IsMateMapped(void) const;         // Returns true if alignment's mate is mapped        \r
+        bool IsMateReverseStrand(void) const;  // Returns true if alignment's mate mapped to reverse strand        \r
+        bool IsPaired(void) const;             // Returns true if alignment part of paired-end read        \r
+        bool IsPrimaryAlignment(void) const;   // Returns true if reported position is primary alignment       \r
+        bool IsProperPair(void) const;         // Returns true if alignment is part of read that satisfied paired-end resolution     \r
+        bool IsReverseStrand(void) const;      // Returns true if alignment mapped to reverse strand\r
+        bool IsSecondMate(void) const;         // Returns true if alignment is second mate on read\r
+\r
+    // Manipulate alignment flags\r
+    public:        \r
+        void SetIsDuplicate(bool ok);          // Sets "PCR duplicate" flag        \r
+        void SetIsFailedQC(bool ok);           // Sets "failed quality control" flag        \r
+        void SetIsFirstMate(bool ok);          // Sets "alignment is first mate" flag        \r
+        void SetIsMateUnmapped(bool ok);       // Sets "alignment's mate is mapped" flag        \r
+        void SetIsMateReverseStrand(bool ok);  // Sets "alignment's mate mapped to reverse strand" flag        \r
+        void SetIsPaired(bool ok);             // Sets "alignment part of paired-end read" flag        \r
+       void SetIsProperPair(bool ok);          // Sets "alignment is part of read that satisfied paired-end resolution" flag        \r
+        void SetIsReverseStrand(bool ok);      // Sets "alignment mapped to reverse strand" flag        \r
+        void SetIsSecondaryAlignment(bool ok); // Sets "position is primary alignment" flag        \r
+        void SetIsSecondMate(bool ok);         // Sets "alignment is second mate on read" flag        \r
+        void SetIsUnmapped(bool ok);           // Sets "alignment is mapped" flag\r
+
+    // Tag data access methods
     public:\r
-        // Sets "PCR duplicate" bit \r
-        void SetIsDuplicate(bool ok) { if (ok) AlignmentFlag |= DUPLICATE; else AlignmentFlag &= ~DUPLICATE; }\r
-        // Sets "failed quality control" bit\r
-        void SetIsFailedQC(bool ok) { if (ok) AlignmentFlag |= QC_FAILED; else AlignmentFlag &= ~QC_FAILED; }\r
-        // Sets "alignment is first mate" bit\r
-        void SetIsFirstMate(bool ok) { if (ok) AlignmentFlag |= READ_1; else AlignmentFlag &= ~READ_1; }\r
-        // Sets "alignment's mate is mapped" bit\r
-        void SetIsMateUnmapped(bool ok) { if (ok) AlignmentFlag |= MATE_UNMAPPED; else AlignmentFlag &= ~MATE_UNMAPPED; }\r
-        // Sets "alignment's mate mapped to reverse strand" bit\r
-        void SetIsMateReverseStrand(bool ok) { if (ok) AlignmentFlag |= MATE_REVERSE; else AlignmentFlag &= ~MATE_REVERSE; }\r
-        // Sets "alignment part of paired-end read" bit\r
-        void SetIsPaired(bool ok) { if (ok) AlignmentFlag |= PAIRED; else AlignmentFlag &= ~PAIRED; }\r
-        // Sets "alignment is part of read that satisfied paired-end resolution" bit\r
-        void SetIsProperPair(bool ok) { if (ok) AlignmentFlag |= PROPER_PAIR; else AlignmentFlag &= ~PROPER_PAIR; }\r
-        // Sets "alignment mapped to reverse strand" bit\r
-        void SetIsReverseStrand(bool ok) { if (ok) AlignmentFlag |= REVERSE; else AlignmentFlag &= ~REVERSE; }\r
-        // Sets "position is primary alignment (determined by external app)"\r
-        void SetIsSecondaryAlignment(bool ok)  { if (ok) AlignmentFlag |= SECONDARY; else AlignmentFlag &= ~SECONDARY; }\r
-        // Sets "alignment is second mate on read" bit\r
-        void SetIsSecondMate(bool ok) { if (ok) AlignmentFlag |= READ_2; else AlignmentFlag &= ~READ_2; }\r
-        // Sets "alignment is mapped" bit\r
-        void SetIsUnmapped(bool ok) { if (ok) AlignmentFlag |= UNMAPPED; else AlignmentFlag &= ~UNMAPPED; }\r
-\r
+        bool GetEditDistance(uint8_t& editDistance) const;     // get "NM" tag data - contributed by Aaron Quinlan\r
+        bool GetReadGroup(std::string& readGroup) const;       // get "RG" tag data\r
+
+    // Additional data access methods\r
     public:\r
-\r
-        // get "RG" tag data\r
-        bool GetReadGroup(std::string& readGroup) const {\r
-\r
-            if ( TagData.empty() ) { return false; }\r
-\r
-            // localize the tag data\r
-            char* pTagData = (char*)TagData.data();\r
-            const unsigned int tagDataLen = TagData.size();\r
-            unsigned int numBytesParsed = 0;\r
-\r
-            bool foundReadGroupTag = false;\r
-            while( numBytesParsed < tagDataLen ) {\r
-\r
-                const char* pTagType = pTagData;\r
-                const char* pTagStorageType = pTagData + 2;\r
-                pTagData       += 3;\r
-                numBytesParsed += 3;\r
-\r
-                // check the current tag\r
-                if ( std::strncmp(pTagType, "RG", 2) == 0 ) {\r
-                    foundReadGroupTag = true;\r
-                    break;\r
-                }\r
-\r
-                // get the storage class and find the next tag\r
-                if (*pTagStorageType == '\0') { return false; }\r
-                SkipToNextTag( *pTagStorageType, pTagData, numBytesParsed );\r
-                if (*pTagData == '\0') { return false; }\r
-            }\r
-\r
-            // return if the read group tag was not present\r
-            if ( !foundReadGroupTag ) { return false; }\r
-\r
-            // assign the read group\r
-            const unsigned int readGroupLen = std::strlen(pTagData);\r
-            readGroup.resize(readGroupLen);\r
-            std::memcpy( (char*)readGroup.data(), pTagData, readGroupLen );\r
-            return true;\r
-        }\r
-\r
-        // get "NM" tag data - contributed by Aaron Quinlan\r
-        bool GetEditDistance(uint8_t& editDistance) const {\r
-\r
-            if ( TagData.empty() ) { return false; }\r
-\r
-            // localize the tag data\r
-            char* pTagData = (char*)TagData.data();\r
-            const unsigned int tagDataLen = TagData.size();\r
-            unsigned int numBytesParsed = 0;\r
-\r
-            bool foundEditDistanceTag = false;\r
-            while( numBytesParsed < tagDataLen ) {\r
-\r
-                const char* pTagType = pTagData;\r
-                const char* pTagStorageType = pTagData + 2;\r
-                pTagData       += 3;\r
-                numBytesParsed += 3;\r
-\r
-                // check the current tag\r
-                if ( strncmp(pTagType, "NM", 2) == 0 ) {\r
-                    foundEditDistanceTag = true;\r
-                    break;\r
-                }\r
-\r
-                // get the storage class and find the next tag\r
-                if (*pTagStorageType == '\0') { return false; }\r
-                SkipToNextTag( *pTagStorageType, pTagData, numBytesParsed );\r
-                if (*pTagData == '\0') { return false; }\r
-            }\r
-            // return if the edit distance tag was not present\r
-            if ( !foundEditDistanceTag ) { return false; }\r
-\r
-            // assign the editDistance value\r
-            std::memcpy(&editDistance, pTagData, 1);\r
-            return true;\r
-        }\r
-\r
+       int GetEndPosition(bool usePadded = false) const;       // calculates alignment end position, based on starting position and CIGAR operations
+
+    // 'internal' utility methods \r
     private:\r
-        static void SkipToNextTag(const char storageType, char* &pTagData, unsigned int& numBytesParsed) {\r
-            switch(storageType) {\r
-\r
-                case 'A':\r
-                case 'c':\r
-                case 'C':\r
-                        ++numBytesParsed;\r
-                        ++pTagData;\r
-                        break;\r
-\r
-                case 's':\r
-                case 'S':\r
-                        numBytesParsed += 2;\r
-                        pTagData       += 2;\r
-                        break;\r
-\r
-                case 'f':\r
-                case 'i':\r
-                case 'I':\r
-                        numBytesParsed += 4;\r
-                        pTagData       += 4;\r
-                        break;\r
-\r
-                case 'Z':\r
-                case 'H':\r
-                        while(*pTagData) {\r
-                            ++numBytesParsed;\r
-                            ++pTagData;\r
-                        }\r
-                        // ---------------------------\r
-                        // Added: 3-25-2010 DWB\r
-                        // Contributed: ARQ\r
-                        // Fixed: error parsing variable length tag data\r
-                        ++pTagData;\r
-                        // ---------------------------\r
-                        break;\r
-\r
-                default:\r
-                        printf("ERROR: Unknown tag storage class encountered: [%c]\n", *pTagData);\r
-                        exit(1);\r
-            }\r
-        }\r
+        static void SkipToNextTag(const char storageType, char* &pTagData, unsigned int& numBytesParsed);\r
 \r
     // Data members\r
     public:\r
@@ -257,19 +131,20 @@ struct BamAlignment {
         int32_t      MatePosition;      // Position (0-based) where alignment's mate starts\r
         int32_t      InsertSize;        // Mate-pair insert size\r
 \r
-    // Alignment flag query constants\r
+    // Alignment flag query constants
+    // Use the get/set methods above instead\r
     private:\r
-        enum { PAIRED        = 1,\r
-               PROPER_PAIR   = 2,\r
-               UNMAPPED      = 4,\r
-               MATE_UNMAPPED = 8,\r
-               REVERSE       = 16,\r
-               MATE_REVERSE  = 32,\r
-               READ_1        = 64,\r
-               READ_2        = 128,\r
-               SECONDARY     = 256,\r
-               QC_FAILED     = 512,\r
-               DUPLICATE     = 1024\r
+        enum { PAIRED        = 1\r
+             , PROPER_PAIR   = 2\r
+             , UNMAPPED      = 4\r
+             , MATE_UNMAPPED = 8\r
+             , REVERSE       = 16\r
+             , MATE_REVERSE  = 32\r
+             , READ_1        = 64\r
+             , READ_2        = 128\r
+             , SECONDARY     = 256\r
+             , QC_FAILED     = 512\r
+             , DUPLICATE     = 1024 \r
              };\r
 };\r
 \r
@@ -282,14 +157,17 @@ struct CigarOp {
 };\r
 \r
 struct RefData {\r
+   
     // data members\r
     std::string RefName;          // Name of reference sequence\r
     int32_t     RefLength;        // Length of reference sequence\r
     bool        RefHasAlignments; // True if BAM file contains alignments mapped to reference sequence\r
+    
     // constructor\r
-    RefData(void)\r
-        : RefLength(0)\r
-        , RefHasAlignments(false)\r
+    RefData(const int32_t& length = 0, 
+            bool ok = false)\r
+        : RefLength(length)\r
+        , RefHasAlignments(ok)\r
     { }\r
 };\r
 \r
@@ -299,12 +177,15 @@ typedef std::vector<BamAlignment> BamAlignmentVector;
 // ----------------------------------------------------------------\r
 // Indexing structs & typedefs\r
 \r
-struct Chunk {\r
+struct Chunk {
+\r
     // data members\r
     uint64_t Start;\r
     uint64_t Stop;\r
+
     // constructor\r
-    Chunk(const uint64_t& start = 0, const uint64_t& stop = 0)\r
+    Chunk(const uint64_t& start = 0, 
+          const uint64_t& stop = 0)\r
         : Start(start)\r
         , Stop(stop)\r
     { }\r
@@ -332,6 +213,209 @@ struct ReferenceIndex {
 };\r
 \r
 typedef std::vector<ReferenceIndex> BamIndex;\r
+
+// ----------------------------------------------------------------
+// BamAlignment member methods
+
+// constructors & destructor
+inline 
+BamAlignment::BamAlignment(void) { }
+
+inline 
+BamAlignment::BamAlignment(const BamAlignment& other)
+    : Name(other.Name)
+    , Length(other.Length)
+    , QueryBases(other.QueryBases)
+    , AlignedBases(other.AlignedBases)
+    , Qualities(other.Qualities)
+    , TagData(other.TagData)
+    , RefID(other.RefID)
+    , Position(other.Position)
+    , Bin(other.Bin)
+    , MapQuality(other.MapQuality)
+    , AlignmentFlag(other.AlignmentFlag)
+    , CigarData(other.CigarData)
+    , MateRefID(other.MateRefID)
+    , MatePosition(other.MatePosition)
+    , InsertSize(other.InsertSize)
+{ }
+
+inline 
+BamAlignment::~BamAlignment(void) { }
+
+// Queries against alignment flags\r
+inline bool BamAlignment::IsDuplicate(void) const         { return ( (AlignmentFlag & DUPLICATE)     != 0 ); }\r
+inline bool BamAlignment::IsFailedQC(void) const          { return ( (AlignmentFlag & QC_FAILED)     != 0 ); }\r
+inline bool BamAlignment::IsFirstMate(void) const         { return ( (AlignmentFlag & READ_1)        != 0 ); }\r
+inline bool BamAlignment::IsMapped(void) const            { return ( (AlignmentFlag & UNMAPPED)      == 0 ); }\r
+inline bool BamAlignment::IsMateMapped(void) const        { return ( (AlignmentFlag & MATE_UNMAPPED) == 0 ); }\r
+inline bool BamAlignment::IsMateReverseStrand(void) const { return ( (AlignmentFlag & MATE_REVERSE)  != 0 ); }\r
+inline bool BamAlignment::IsPaired(void) const            { return ( (AlignmentFlag & PAIRED)        != 0 ); }\r
+inline bool BamAlignment::IsPrimaryAlignment(void) const  { return ( (AlignmentFlag & SECONDARY)     == 0 ); }\r
+inline bool BamAlignment::IsProperPair(void) const        { return ( (AlignmentFlag & PROPER_PAIR)   != 0 ); }\r
+inline bool BamAlignment::IsReverseStrand(void) const     { return ( (AlignmentFlag & REVERSE)       != 0 ); }\r
+inline bool BamAlignment::IsSecondMate(void) const        { return ( (AlignmentFlag & READ_2)        != 0 ); }
+
+// Manipulate alignment flags \r
+inline void BamAlignment::SetIsDuplicate(bool ok)          { if (ok) AlignmentFlag |= DUPLICATE;     else AlignmentFlag &= ~DUPLICATE; }\r
+inline void BamAlignment::SetIsFailedQC(bool ok)           { if (ok) AlignmentFlag |= QC_FAILED;     else AlignmentFlag &= ~QC_FAILED; }\r
+inline void BamAlignment::SetIsFirstMate(bool ok)          { if (ok) AlignmentFlag |= READ_1;        else AlignmentFlag &= ~READ_1; }\r
+inline void BamAlignment::SetIsMateUnmapped(bool ok)       { if (ok) AlignmentFlag |= MATE_UNMAPPED; else AlignmentFlag &= ~MATE_UNMAPPED; }\r
+inline void BamAlignment::SetIsMateReverseStrand(bool ok)  { if (ok) AlignmentFlag |= MATE_REVERSE;  else AlignmentFlag &= ~MATE_REVERSE; }\r
+inline void BamAlignment::SetIsPaired(bool ok)             { if (ok) AlignmentFlag |= PAIRED;        else AlignmentFlag &= ~PAIRED; }\r
+inline void BamAlignment::SetIsProperPair(bool ok)         { if (ok) AlignmentFlag |= PROPER_PAIR;   else AlignmentFlag &= ~PROPER_PAIR; }\r
+inline void BamAlignment::SetIsReverseStrand(bool ok)      { if (ok) AlignmentFlag |= REVERSE;       else AlignmentFlag &= ~REVERSE; }\r
+inline void BamAlignment::SetIsSecondaryAlignment(bool ok) { if (ok) AlignmentFlag |= SECONDARY;     else AlignmentFlag &= ~SECONDARY; }\r
+inline void BamAlignment::SetIsSecondMate(bool ok)         { if (ok) AlignmentFlag |= READ_2;        else AlignmentFlag &= ~READ_2; }\r
+inline void BamAlignment::SetIsUnmapped(bool ok)           { if (ok) AlignmentFlag |= UNMAPPED;      else AlignmentFlag &= ~UNMAPPED; }
+
+// calculates alignment end position, based on starting position and CIGAR operations
+inline \r
+int BamAlignment::GetEndPosition(bool usePadded) const {\r
+\r
+    // initialize alignment end to starting position\r
+    int alignEnd = Position;\r
+\r
+    // iterate over cigar operations\r
+    std::vector<CigarOp>::const_iterator cigarIter = CigarData.begin();\r
+    std::vector<CigarOp>::const_iterator cigarEnd  = CigarData.end();\r
+    for ( ; cigarIter != cigarEnd; ++cigarIter) {\r
+       const char cigarType = (*cigarIter).Type;\r
+       if ( cigarType == 'M' || cigarType == 'D' || cigarType == 'N' ) {\r
+           alignEnd += (*cigarIter).Length;\r
+       } 
+        else if ( usePadded && cigarType == 'I' ) {
+            alignEnd += (*cigarIter).Length;
+        }\r
+    }\r
+    return alignEnd;\r
+}\r
+\r
+// get "NM" tag data - contributed by Aaron Quinlan
+// stores data in 'editDistance', returns success/fail
+inline \r
+bool BamAlignment::GetEditDistance(uint8_t& editDistance) const {\r
+\r
+    if ( TagData.empty() ) { return false; }\r
+\r
+    // localize the tag data\r
+    char* pTagData = (char*)TagData.data();\r
+    const unsigned int tagDataLen = TagData.size();\r
+    unsigned int numBytesParsed = 0;\r
+\r
+    bool foundEditDistanceTag = false;\r
+    while( numBytesParsed < tagDataLen ) {\r
+\r
+        const char* pTagType = pTagData;\r
+        const char* pTagStorageType = pTagData + 2;\r
+        pTagData       += 3;\r
+        numBytesParsed += 3;\r
+\r
+        // check the current tag\r
+        if ( strncmp(pTagType, "NM", 2) == 0 ) {\r
+            foundEditDistanceTag = true;\r
+            break;\r
+        }\r
+\r
+        // get the storage class and find the next tag\r
+        if (*pTagStorageType == '\0') { return false; }\r
+        SkipToNextTag( *pTagStorageType, pTagData, numBytesParsed );\r
+        if (*pTagData == '\0') { return false; }\r
+    }\r
+    // return if the edit distance tag was not present\r
+    if ( !foundEditDistanceTag ) { return false; }\r
+\r
+    // assign the editDistance value\r
+    std::memcpy(&editDistance, pTagData, 1);\r
+    return true;\r
+}
+
+// get "RG" tag data
+// stores data in 'readGroup', returns success/fail
+inline \r
+bool BamAlignment::GetReadGroup(std::string& readGroup) const {\r
+\r
+    if ( TagData.empty() ) { return false; }\r
+\r
+    // localize the tag data\r
+    char* pTagData = (char*)TagData.data();\r
+    const unsigned int tagDataLen = TagData.size();\r
+    unsigned int numBytesParsed = 0;\r
+\r
+    bool foundReadGroupTag = false;\r
+    while( numBytesParsed < tagDataLen ) {\r
+\r
+        const char* pTagType = pTagData;\r
+        const char* pTagStorageType = pTagData + 2;\r
+        pTagData       += 3;\r
+        numBytesParsed += 3;\r
+\r
+        // check the current tag\r
+        if ( std::strncmp(pTagType, "RG", 2) == 0 ) {\r
+            foundReadGroupTag = true;\r
+            break;\r
+        }\r
+\r
+        // get the storage class and find the next tag\r
+        if (*pTagStorageType == '\0') { return false; }\r
+        SkipToNextTag( *pTagStorageType, pTagData, numBytesParsed );\r
+        if (*pTagData == '\0') { return false; }\r
+    }\r
+\r
+    // return if the read group tag was not present\r
+    if ( !foundReadGroupTag ) { return false; }\r
+\r
+    // assign the read group\r
+    const unsigned int readGroupLen = std::strlen(pTagData);\r
+    readGroup.resize(readGroupLen);\r
+    std::memcpy( (char*)readGroup.data(), pTagData, readGroupLen );\r
+    return true;\r
+}
+
+inline
+void BamAlignment::SkipToNextTag(const char storageType, char* &pTagData, unsigned int& numBytesParsed) {\r
+    
+    switch(storageType) {\r
+\r
+        case 'A':\r
+        case 'c':\r
+        case 'C':\r
+            ++numBytesParsed;\r
+            ++pTagData;\r
+            break;\r
+\r
+        case 's':\r
+        case 'S':\r
+            numBytesParsed += 2;\r
+            pTagData       += 2;\r
+            break;\r
+\r
+        case 'f':\r
+        case 'i':\r
+        case 'I':\r
+            numBytesParsed += 4;\r
+            pTagData       += 4;\r
+            break;\r
+\r
+        case 'Z':\r
+        case 'H':\r
+            while(*pTagData) {\r
+                ++numBytesParsed;\r
+                ++pTagData;\r
+            }\r
+        // ---------------------------\r
+        // Added: 3-25-2010 DWB\r
+        // Contributed: ARQ\r
+        // Fixed: error parsing variable length tag data\r
+            ++pTagData;\r
+        // ---------------------------\r
+            break;\r
+\r
+        default:\r
+            printf("ERROR: Unknown tag storage class encountered: [%c]\n", *pTagData);\r
+            exit(1);\r
+    }\r
+}
 \r
 // ----------------------------------------------------------------\r
 // Added: 3-35-2010 DWB\r
@@ -347,7 +431,7 @@ inline bool SystemIsBigEndian(void) {
 // swaps endianness of 16-bit value 'in place'\r
 inline void SwapEndian_16(int16_t& x) {\r
     x = ((x >> 8) | (x << 8));\r
-}\r
+}
 \r
 inline void SwapEndian_16(uint16_t& x) {\r
     x = ((x >> 8) | (x << 8));\r
@@ -360,7 +444,7 @@ inline void SwapEndian_32(int32_t& x) {
          ((x >> 8) & 0x0000FF00) | \r
           (x << 24)\r
         );\r
-}\r
+}
 \r
 inline void SwapEndian_32(uint32_t& x) {\r
     x = ( (x >> 24) | \r
@@ -394,17 +478,20 @@ inline void SwapEndian_64(uint64_t& x) {
           (x << 56)\r
         );\r
 }\r
-\r
+
+// swaps endianness of 'next 2 bytes' in a char buffer (in-place)\r
 inline void SwapEndian_16p(char* data) {\r
     uint16_t& value = (uint16_t&)*data; \r
     SwapEndian_16(value);\r
 }\r
-\r
+
+// swaps endianness of 'next 4 bytes' in a char buffer (in-place)\r
 inline void SwapEndian_32p(char* data) {\r
     uint32_t& value = (uint32_t&)*data; \r
     SwapEndian_32(value);\r
 }\r
-\r
+
+// swaps endianness of 'next 8 bytes' in a char buffer (in-place)\r
 inline void SwapEndian_64p(char* data) {\r
     uint64_t& value = (uint64_t&)*data; \r
     SwapEndian_64(value);\r
index ff20c11df3447588785cc8016c840b93363329f2..a2f975f9659032bed75b5cb280b12a97e97b94df 100644 (file)
@@ -3,7 +3,7 @@
 // Marth Lab, Department of Biology, Boston College\r
 // All rights reserved.\r
 // ---------------------------------------------------------------------------\r
-// Last modified: 6 April 2010 (DB)\r
+// Last modified: 14 April 2010 (DB)\r
 // ---------------------------------------------------------------------------\r
 // Uses BGZF routines were adapted from the bgzf.c code developed at the Broad\r
 // Institute.\r
@@ -39,7 +39,7 @@ struct BamReader::BamReaderPrivate {
     // data members\r
     // -------------------------------\r
 \r
-    // general data\r
+    // general file data\r
     BgzfData  mBGZF;\r
     string    HeaderText;\r
     BamIndex  Index;\r
@@ -48,7 +48,8 @@ struct BamReader::BamReaderPrivate {
     int64_t   AlignmentsBeginOffset;\r
     string    Filename;\r
     string    IndexFilename;\r
-    \r
+    
+    // system data\r
     bool IsBigEndian;\r
 \r
     // user-specified region values\r
@@ -95,8 +96,6 @@ struct BamReader::BamReaderPrivate {
     int BinsFromRegion(int refID, int left, uint16_t[MAX_BIN]);\r
     // fills out character data for BamAlignment data\r
     bool BuildCharData(BamAlignment& bAlignment, const BamAlignmentSupportData& supportData);\r
-    // calculates alignment end position based on starting position and provided CIGAR operations\r
-    int CalculateAlignmentEnd(const int& position, const std::vector<CigarOp>& cigarData);\r
     // calculate file offset for first alignment chunk overlapping 'left'\r
     int64_t GetOffset(int refID, int left);\r
     // checks to see if alignment overlaps current region\r
@@ -465,24 +464,6 @@ bool BamReader::BamReaderPrivate::BuildIndex(void) {
     return Rewind();\r
 }\r
 \r
-// calculates alignment end position based on starting position and provided CIGAR operations\r
-int BamReader::BamReaderPrivate::CalculateAlignmentEnd(const int& position, const vector<CigarOp>& cigarData) {\r
-\r
-    // initialize alignment end to starting position\r
-    int alignEnd = position;\r
-\r
-    // iterate over cigar operations\r
-    vector<CigarOp>::const_iterator cigarIter = cigarData.begin();\r
-    vector<CigarOp>::const_iterator cigarEnd  = cigarData.end();\r
-    for ( ; cigarIter != cigarEnd; ++cigarIter) {\r
-        char cigarType = (*cigarIter).Type;\r
-        if ( cigarType == 'M' || cigarType == 'D' || cigarType == 'N' ) {\r
-            alignEnd += (*cigarIter).Length;\r
-        }\r
-    }\r
-    return alignEnd;\r
-}\r
-\r
 \r
 // clear index data structure\r
 void BamReader::BamReaderPrivate::ClearIndex(void) {\r
@@ -633,8 +614,8 @@ void BamReader::BamReaderPrivate::InsertLinearOffset(LinearOffsetVector& offsets
                                                      const uint64_t&     lastOffset)\r
 {\r
     // get converted offsets\r
-    int beginOffset = bAlignment.Position >> BAM_LIDX_SHIFT;\r
-    int endOffset   = ( CalculateAlignmentEnd(bAlignment.Position, bAlignment.CigarData) - 1) >> BAM_LIDX_SHIFT;\r
+    int beginOffset = bAlignment.Position >> BAM_LIDX_SHIFT;
+    int endOffset   = (bAlignment.GetEndPosition() - 1) >> BAM_LIDX_SHIFT;\r
 \r
     // resize vector if necessary\r
     int oldSize = offsets.size();\r
@@ -658,8 +639,8 @@ bool BamReader::BamReaderPrivate::IsOverlap(BamAlignment& bAlignment) {
     // read starts after left boundary\r
     if ( bAlignment.Position >= CurrentLeft) { return true; }\r
 \r
-    // return whether alignment end overlaps left boundary\r
-    return ( CalculateAlignmentEnd(bAlignment.Position, bAlignment.CigarData) >= CurrentLeft );\r
+    // return whether alignment end overlaps left boundary
+    return ( bAlignment.GetEndPosition() >= CurrentLeft );\r
 }\r
 \r
 // jumps to specified region(refID, leftBound) in BAM file, returns success/fail\r
@@ -894,12 +875,10 @@ bool BamReader::BamReaderPrivate::LoadNextAlignment(BamAlignment& bAlignment, Ba
     else {\r
      \r
         // store alignment name and length\r
-//         bAlignment.Name.clear();\r
         bAlignment.Name.assign((const char*)(allCharData));\r
         bAlignment.Length = supportData.QuerySequenceLength;\r
       \r
         // store remaining 'allCharData' in supportData structure\r
-//         supportData.AllCharData.clear();\r
         supportData.AllCharData.assign((const char*)allCharData, dataLength);\r
         \r
         // save CigarOps for BamAlignment\r