]> git.donarmstrong.com Git - bamtools.git/blobdiff - src/api/BamAlignment.cpp
Removed some debugging 'error string' messages that snuck into last
[bamtools.git] / src / api / BamAlignment.cpp
index 5cc138be6dfebaac1102db0a81b54f86118afa2b..0b13fb4121786277de72218c676fc29f38c4d648 100644 (file)
@@ -2,13 +2,13 @@
 // BamAlignment.cpp (c) 2009 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
 // BamAlignment.cpp (c) 2009 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 8 October 2011 (DB)
+// Last modified: 17 October 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides the BamAlignment data structure
 // ***************************************************************************
 
 // ---------------------------------------------------------------------------
 // Provides the BamAlignment data structure
 // ***************************************************************************
 
-#include <api/BamAlignment.h>
-#include <api/BamConstants.h>
+#include "api/BamAlignment.h"
+#include "api/BamConstants.h"
 using namespace BamTools;
 using namespace std;
 
 using namespace BamTools;
 using namespace std;
 
@@ -105,31 +105,6 @@ BamAlignment::BamAlignment(const BamAlignment& other)
 */
 BamAlignment::~BamAlignment(void) { }
 
 */
 BamAlignment::~BamAlignment(void) { }
 
-///*! \fn bool BamAlignment::AddTag(const std::string& tag, const std::string& type, const std::string& value)
-//    \brief Adds a field with string data to the BAM tags.
-
-//    Does NOT modify an existing tag - use \link BamAlignment::EditTag() \endlink instead.
-
-//    \param[in] tag   2-character tag name
-//    \param[in] type  1-character tag type (must be "Z" or "H")
-//    \param[in] value string data to store
-//    \return \c true if the \b new tag was added successfully
-//    \sa \samSpecURL for more details on reserved tag names, supported tag types, etc.
-//*/
-
-
-///*! \fn bool AddTag(const std::string& tag, const std::vector<uint8_t>& values);
-//    \brief Adds a numeric array field to the BAM tags.
-
-//    Does NOT modify an existing tag - use \link BamAlignment::EditTag() \endlink instead.
-
-//    \param tag    2-character tag name
-//    \param values vector of uint8_t values to store
-
-//    \return \c true if the \b new tag was added successfully
-//    \sa \samSpecURL for more details on reserved tag names, supported tag types, etc.
-//*/
-
 /*! \fn bool BamAlignment::BuildCharData(void)
     \brief Populates alignment string fields (read name, bases, qualities, tag data).
 
 /*! \fn bool BamAlignment::BuildCharData(void)
     \brief Populates alignment string fields (read name, bases, qualities, tag data).
 
@@ -351,49 +326,20 @@ bool BamAlignment::BuildCharData(void) {
         memcpy((char*)(TagData.data()), tagData, tagDataLength);
     }
 
         memcpy((char*)(TagData.data()), tagData, tagDataLength);
     }
 
-    // clear the core-only flag
+    // clear core-only flag & return success
     SupportData.HasCoreOnly = false;
     SupportData.HasCoreOnly = false;
-
-    // return success
     return true;
 }
 
     return true;
 }
 
-///*! \fn bool BamAlignment::EditTag(const std::string& tag, const std::string& type, const std::string& value)
-//    \brief Edits a BAM tag field containing string data.
-
-//    If \a tag does not exist, a new entry is created.
-
-//    \param tag   2-character tag name
-//    \param type  1-character tag type (must be "Z" or "H")
-//    \param value string data to store
-
-//    \return \c true if the tag was modified/created successfully
-
-//    \sa BamAlignment::RemoveTag()
-//    \sa \samSpecURL for more details on reserved tag names, supported tag types, etc.
-//*/
-
-///*! \fn bool EditTag(const std::string& tag, const std::vector<uint8_t>& values);
-//    \brief Edits a BAM tag field containing a numeric array.
-
-//    If \a tag does not exist, a new entry is created.
-
-//    \param tag   2-character tag name
-//    \param value vector of uint8_t values to store
-
-//    \return \c true if the tag was modified/created successfully
-//    \sa \samSpecURL for more details on reserved tag names, supported tag types, etc.
-//*/
-
-/*! \fn bool BamAlignment::FindTag(const std::string& tag, char*& pTagData, const unsigned int& tagDataLength, unsigned int& numBytesParsed)
+/*! \fn bool BamAlignment::FindTag(const std::string& tag, char*& pTagData, const unsigned int& tagDataLength, unsigned int& numBytesParsed) const
     \internal
 
     Searches for requested tag in BAM tag data.
 
     \internal
 
     Searches for requested tag in BAM tag data.
 
-    \param tag            requested 2-character tag name
-    \param pTagData       pointer to current position in BamAlignment::TagData
-    \param tagDataLength  length of BamAlignment::TagData
-    \param numBytesParsed number of bytes parsed so far
+    \param[in]     tag            requested 2-character tag name
+    \param[in,out] pTagData       pointer to current position in BamAlignment::TagData
+    \param[in]     tagDataLength  length of BamAlignment::TagData
+    \param[in,out] numBytesParsed number of bytes parsed so far
 
     \return \c true if found
 
 
     \return \c true if found
 
@@ -428,39 +374,18 @@ bool BamAlignment::FindTag(const std::string& tag,
     return false;
 }
 
     return false;
 }
 
-/*! \fn bool BamAlignment::GetEditDistance(uint32_t& editDistance) const
-    \brief Retrieves value of edit distance tag ("NM").
-
-    \deprecated Instead use BamAlignment::GetTag()
-        \code
-            BamAlignment::GetTag("NM", editDistance);
-        \endcode
-
-    \param editDistance destination for retrieved value
-
-    \return \c true if found
-*/
-
-// TODO : REMOVE THIS METHOD
-bool BamAlignment::GetEditDistance(uint32_t& editDistance) const {
-    return GetTag("NM", (uint32_t&)editDistance);
-}
-
-/*! \fn int BamAlignment::GetEndPosition(bool usePadded = false, bool closedInterval = USE_CLOSED_DEFAULT) const
-    \brief Calculates alignment end position, based on starting position and CIGAR data.
+/*! \fn int BamAlignment::GetEndPosition(bool usePadded = false, bool closedInterval = false) const
+    \brief Calculates alignment end position, based on its starting position and CIGAR data.
 
     \warning The position returned now represents a zero-based, HALF-OPEN interval.
     In previous versions of BamTools (0.x & 1.x) all intervals were treated
 
     \warning The position returned now represents a zero-based, HALF-OPEN interval.
     In previous versions of BamTools (0.x & 1.x) all intervals were treated
-    as zero-based, CLOSED. I whole-heartedly apologize for any inconsistencies this
-    may have caused if you assumed that BT was always half-open; full aplogies also
-    to those who recognized that BamTools originally used a closed interval, but may
-    need to update their code to reflect this new change.
-
-    \param usePadded Allow inserted bases to affect the reported position. Default is false, so that
-                     reported position stays synced with reference coordinates.
+    as zero-based, CLOSED.
 
 
-    \param closedInterval Setting this to true will return a 0-based end coordinate. Default is false,
-                          so that his value represents a standard, half-open interval.
+    \param[in] usePadded      Allow inserted bases to affect the reported position. Default is
+                              false, so that reported position stays synced with reference
+                              coordinates.
+    \param[in] closedInterval Setting this to true will return a 0-based end coordinate. Default is
+                              false, so that his value represents a standard, half-open interval.
 
     \return alignment end position
 */
 
     \return alignment end position
 */
@@ -486,7 +411,7 @@ int BamAlignment::GetEndPosition(bool usePadded, bool closedInterval) const {
                 alignEnd += op.Length;
                 break;
 
                 alignEnd += op.Length;
                 break;
 
-            // increase end position when CIGAR char is 'I' only if @usePadded is true
+            // increase end position on insertion, only if @usePadded is true
             case Constants::BAM_CIGAR_INS_CHAR :
                 if ( usePadded )
                     alignEnd += op.Length;
             case Constants::BAM_CIGAR_INS_CHAR :
                 if ( usePadded )
                     alignEnd += op.Length;
@@ -507,58 +432,110 @@ int BamAlignment::GetEndPosition(bool usePadded, bool closedInterval) const {
 }
 
 /*! \fn std::string BamAlignment::GetErrorString(void) const
 }
 
 /*! \fn std::string BamAlignment::GetErrorString(void) const
-    \brief Returns a description of the last error that occurred
+    \brief Returns a human-readable description of the last error that occurred
 
 
-    This method allows elimnation of STDERR pollution. Developers of client code
+    This method allows elimination of STDERR pollution. Developers of client code
     may choose how the messages are displayed to the user, if at all.
 
     may choose how the messages are displayed to the user, if at all.
 
-    \return description of last error that occurred
+    \return error description
 */
 std::string BamAlignment::GetErrorString(void) const {
     return ErrorString;
 }
 
 */
 std::string BamAlignment::GetErrorString(void) const {
     return ErrorString;
 }
 
-/*! \fn bool BamAlignment::GetReadGroup(std::string& readGroup) const
-    \brief Retrieves value of read group tag ("RG").
+/*! \fn bool BamAlignment::GetSoftClips(std::vector<int>& clipSizes, std::vector<int>& readPositions, std::vector<int>& genomePositions, bool usePadded = false) const
+    \brief Identifies if an alignment has a soft clip. If so, identifies the
+           sizes of the soft clips, as well as their positions in the read and reference.
 
 
-    \deprecated Instead use BamAlignment::GetTag()
-        \code
-            BamAlignment::GetTag("RG", readGroup);
-        \endcode
+    \param[out] clipSizes       vector of the sizes of each soft clip in the alignment
+    \param[out] readPositions   vector of the 0-based read locations of each soft clip in the alignment.
+                                These positions are basically indexes within the read, not genomic positions.
+    \param[out] genomePositions vector of the 0-based genome locations of each soft clip in the alignment
+    \param[in]  usePadded       inserted bases affect reported position. Default is false, so that
+                                reported position stays 'sync-ed' with reference coordinates.
 
 
-    \param readGroup destination for retrieved value
-
-    \return \c true if found
+    \return \c true if any soft clips were found in the alignment
 */
 */
+bool BamAlignment::GetSoftClips(vector<int>& clipSizes,
+                                vector<int>& readPositions,
+                                vector<int>& genomePositions,
+                                bool usePadded) const
+{
+    // initialize positions & flags
+    int refPosition  = Position;
+    int readPosition = 0;
+    bool softClipFound = false;
+    bool firstCigarOp  = true;
 
 
-// TODO : REMOVE THIS METHOD
-bool BamAlignment::GetReadGroup(std::string& readGroup) const {
-    return GetTag("RG", readGroup);
-}
+    // iterate over cigar operations
+    vector<CigarOp>::const_iterator cigarIter = CigarData.begin();
+    vector<CigarOp>::const_iterator cigarEnd  = CigarData.end();
+    for ( ; cigarIter != cigarEnd; ++cigarIter) {
+        const CigarOp& op = (*cigarIter);
 
 
-///*! \fn bool BamAlignment::GetTag(const std::string& tag, std::string& destination) const
-//    \brief Retrieves the string value associated with a BAM tag.
+        switch ( op.Type ) {
 
 
-//    \param tag         2-character tag name
-//    \param destination destination for retrieved value
+            // increase both read & genome positions on CIGAR chars [DMXN=]
+            case Constants::BAM_CIGAR_DEL_CHAR      :
+            case Constants::BAM_CIGAR_MATCH_CHAR    :
+            case Constants::BAM_CIGAR_MISMATCH_CHAR :
+            case Constants::BAM_CIGAR_REFSKIP_CHAR  :
+            case Constants::BAM_CIGAR_SEQMATCH_CHAR :
+                refPosition  += op.Length;
+                readPosition += op.Length;
+                break;
 
 
-//    \return \c true if found
-//*/
+            // increase read position on insertion, genome position only if @usePadded is true
+            case Constants::BAM_CIGAR_INS_CHAR :
+                readPosition += op.Length;
+                if ( usePadded )
+                    refPosition += op.Length;
+                break;
 
 
-///*! \fn bool BamAlignment::GetTag(const std::string& tag, std::vector<uint32_t>& destination) const
-//    \brief Retrieves the numeric array data associated with a BAM tag
+            case Constants::BAM_CIGAR_SOFTCLIP_CHAR :
+
+                softClipFound = true;
+
+                //////////////////////////////////////////////////////////////////////////////
+                // if we are dealing with the *first* CIGAR operation
+                // for this alignment, we increment the read position so that
+                // the read and genome position of the clip are referring to the same base.
+                // For example, in the alignment below, the ref position would be 4, yet
+                //              the read position would be 0. Thus, to "sync" the two,
+                //              we need to increment the read position by the length of the
+                //              soft clip.
+                // Read:  ATCGTTTCGTCCCTGC
+                // Ref:   GGGATTTCGTCCCTGC
+                // Cigar: SSSSMMMMMMMMMMMM
+                //
+                // NOTE: This only needs to be done if the soft clip is the _first_ CIGAR op.
+                //////////////////////////////////////////////////////////////////////////////
+                if ( firstCigarOp )
+                    readPosition += op.Length;
+
+                // track the soft clip's size, read position, and genome position
+                clipSizes.push_back(op.Length);
+                readPositions.push_back(readPosition);
+                genomePositions.push_back(refPosition);
+
+            // any other CIGAR operations have no effect
+            default :
+                break;
+        }
 
 
-//    \param tag         2-character tag name
-//    \param destination destination for retrieved data
+        // clear our "first pass" flag
+        firstCigarOp = false;
+    }
 
 
-//    \return \c true if found
-//*/
+    // return whether any soft clips found
+    return softClipFound;
+}
 
 /*! \fn bool BamAlignment::GetTagType(const std::string& tag, char& type) const
     \brief Retrieves the BAM tag type-code associated with requested tag name.
 
 
 /*! \fn bool BamAlignment::GetTagType(const std::string& tag, char& type) const
     \brief Retrieves the BAM tag type-code associated with requested tag name.
 
-    \param tag  2-character tag name
-    \param type destination for the retrieved (1-character) tag type
+    \param[in]  tag  2-character tag name
+    \param[out] type retrieved (1-character) type-code
 
     \return \c true if found
     \sa \samSpecURL for more details on reserved tag names, supported tag types, etc.
 
     \return \c true if found
     \sa \samSpecURL for more details on reserved tag names, supported tag types, etc.
@@ -614,7 +591,8 @@ bool BamAlignment::GetTagType(const std::string& tag, char& type) const {
 
 /*! \fn bool BamAlignment::HasTag(const std::string& tag) const
     \brief Returns true if alignment has a record for requested tag.
 
 /*! \fn bool BamAlignment::HasTag(const std::string& tag) const
     \brief Returns true if alignment has a record for requested tag.
-    \param tag 2-character tag name
+
+    \param[in] tag 2-character tag name
     \return \c true if alignment has a record for tag
 */
 bool BamAlignment::HasTag(const std::string& tag) const {
     \return \c true if alignment has a record for tag
 */
 bool BamAlignment::HasTag(const std::string& tag) const {
@@ -709,17 +687,14 @@ bool BamAlignment::IsSecondMate(void) const {
     return ( (AlignmentFlag & Constants::BAM_ALIGNMENT_READ_2) != 0 );
 }
 
     return ( (AlignmentFlag & Constants::BAM_ALIGNMENT_READ_2) != 0 );
 }
 
-/*! \fn bool BamAlignment::IsValidSize(const string& tag, const string& type) const
+/*! \fn bool BamAlignment::IsValidSize(const std::string& tag, const std::string& type) const
     \internal
 
     Checks that tag name & type strings are expected sizes.
     \internal
 
     Checks that tag name & type strings are expected sizes.
-    \a tag  should have length
-    \a type should have length 1
-
-    \param tag  BAM tag name
-    \param type BAM tag type-code
 
 
-    \return \c true if both \a tag and \a type are correct sizes
+    \param tag[in]  BAM tag name
+    \param type[in] BAM tag type-code
+    \return \c true if both input strings are valid sizes
 */
 bool BamAlignment::IsValidSize(const std::string& tag, const std::string& type) const {
     return (tag.size()  == Constants::BAM_TAG_TAGSIZE) &&
 */
 bool BamAlignment::IsValidSize(const std::string& tag, const std::string& type) const {
     return (tag.size()  == Constants::BAM_TAG_TAGSIZE) &&
@@ -728,6 +703,8 @@ bool BamAlignment::IsValidSize(const std::string& tag, const std::string& type)
 
 /*! \fn void BamAlignment::RemoveTag(const std::string& tag)
     \brief Removes field from BAM tags.
 
 /*! \fn void BamAlignment::RemoveTag(const std::string& tag)
     \brief Removes field from BAM tags.
+
+    \param[in] tag 2-character name of field to remove
 */
 void BamAlignment::RemoveTag(const std::string& tag) {
   
 */
 void BamAlignment::RemoveTag(const std::string& tag) {
   
@@ -780,6 +757,9 @@ void BamAlignment::RemoveTag(const std::string& tag) {
     \internal
 
     Sets a formatted error string for this alignment.
     \internal
 
     Sets a formatted error string for this alignment.
+
+    \param[in] where class/method where error occurred
+    \param[in] what  description of error
 */
 void BamAlignment::SetErrorString(const std::string& where, const std::string& what) const {
     static const string SEPARATOR = ": ";
 */
 void BamAlignment::SetErrorString(const std::string& where, const std::string& what) const {
     static const string SEPARATOR = ": ";
@@ -826,15 +806,6 @@ void BamAlignment::SetIsMateMapped(bool ok) {
     else    AlignmentFlag |=  Constants::BAM_ALIGNMENT_MATE_UNMAPPED;
 }
 
     else    AlignmentFlag |=  Constants::BAM_ALIGNMENT_MATE_UNMAPPED;
 }
 
-/*! \fn void BamAlignment::SetIsMateUnmapped(bool ok)
-    \brief Complement of using SetIsMateMapped().
-    \deprecated For sake of symmetry with the query methods
-    \sa IsMateMapped(), SetIsMateMapped()
-*/
-void BamAlignment::SetIsMateUnmapped(bool ok) {
-    SetIsMateMapped(!ok);
-}
-
 /*! \fn void BamAlignment::SetIsMateReverseStrand(bool ok)
     \brief Sets "alignment's mate mapped to reverse strand" flag to \a ok.
 */
 /*! \fn void BamAlignment::SetIsMateReverseStrand(bool ok)
     \brief Sets "alignment's mate mapped to reverse strand" flag to \a ok.
 */
@@ -875,15 +846,6 @@ void BamAlignment::SetIsReverseStrand(bool ok) {
     else    AlignmentFlag &= ~Constants::BAM_ALIGNMENT_REVERSE_STRAND;
 }
 
     else    AlignmentFlag &= ~Constants::BAM_ALIGNMENT_REVERSE_STRAND;
 }
 
-/*! \fn void BamAlignment::SetIsSecondaryAlignment(bool ok)
-    \brief Complement of using SetIsPrimaryAlignment().
-    \deprecated For sake of symmetry with the query methods
-    \sa IsPrimaryAlignment(), SetIsPrimaryAlignment()
-*/
-void BamAlignment::SetIsSecondaryAlignment(bool ok) {
-    SetIsPrimaryAlignment(!ok);
-}
-
 /*! \fn void BamAlignment::SetIsSecondMate(bool ok)
     \brief Sets "alignment is second mate on read" flag to \a ok.
 */
 /*! \fn void BamAlignment::SetIsSecondMate(bool ok)
     \brief Sets "alignment is second mate on read" flag to \a ok.
 */
@@ -892,26 +854,18 @@ void BamAlignment::SetIsSecondMate(bool ok) {
     else    AlignmentFlag &= ~Constants::BAM_ALIGNMENT_READ_2;
 }
 
     else    AlignmentFlag &= ~Constants::BAM_ALIGNMENT_READ_2;
 }
 
-/*! \fn void BamAlignment::SetIsUnmapped(bool ok)
-    \brief Complement of using SetIsMapped().
-    \deprecated For sake of symmetry with the query methods
-    \sa IsMapped(), SetIsMapped()
-*/
-void BamAlignment::SetIsUnmapped(bool ok) {
-    SetIsMapped(!ok);
-}
-
-/*! \fn bool BamAlignment::SkipToNextTag(const char storageType, char*& pTagData, unsigned int& numBytesParsed)
+/*! \fn bool BamAlignment::SkipToNextTag(const char storageType, char*& pTagData, unsigned int& numBytesParsed) const
     \internal
 
     Moves to next available tag in tag data string
 
     \internal
 
     Moves to next available tag in tag data string
 
-    \param storageType    BAM tag type-code that determines how far to move cursor
-    \param pTagData       pointer to current position (cursor) in tag string
-    \param numBytesParsed report of how many bytes were parsed (cumulatively)
+    \param[in]     storageType    BAM tag type-code that determines how far to move cursor
+    \param[in,out] pTagData       pointer to current position (cursor) in tag string
+    \param[in,out] numBytesParsed report of how many bytes were parsed (cumulatively)
 
     \return \c if storageType was a recognized BAM tag type
 
     \return \c if storageType was a recognized BAM tag type
-    \post \a pTagData will point to the byte where the next tag data begins.
+
+    \post \a pTagData       will point to the byte where the next tag data begins.
           \a numBytesParsed will correspond to the cursor's position in the full TagData string.
 */
 bool BamAlignment::SkipToNextTag(const char storageType,
           \a numBytesParsed will correspond to the cursor's position in the full TagData string.
 */
 bool BamAlignment::SkipToNextTag(const char storageType,