- \sa BamAlignment::RemoveTag()
- \sa \samSpecURL for more details on reserved tag names, supported tag types, etc.
-*/
-bool BamAlignment::EditTag(const std::string& tag, const std::string& type, const uint32_t& value) {
-
- // skip if core data not parsed
- if ( SupportData.HasCoreOnly ) return false;
-
- // validate tag/type size & that type is OK for uint32_t value
- if ( !Internal::IsValidSize(tag, type) ) return false;
- if ( type.at(0) == Constants::BAM_TAG_TYPE_FLOAT ||
- type.at(0) == Constants::BAM_TAG_TYPE_STRING ||
- type.at(0) == Constants::BAM_TAG_TYPE_HEX ||
- type.at(0) == Constants::BAM_TAG_TYPE_ARRAY
- )
- {
- return false;
- }
-
- // localize the tag data
- char* pOriginalTagData = (char*)TagData.data();
- char* pTagData = pOriginalTagData;
- const unsigned int originalTagDataLength = TagData.size();
-
- unsigned int newTagDataLength = 0;
- unsigned int numBytesParsed = 0;
-
- // if tag found
- if ( Internal::FindTag(tag, pTagData, originalTagDataLength, numBytesParsed) ) {
-
- // make sure array is more than big enough
- char newTagData[originalTagDataLength + sizeof(value)];
-
- // copy original tag data up til desired tag
- const unsigned int beginningTagDataLength = numBytesParsed;
- newTagDataLength += beginningTagDataLength;
- memcpy(newTagData, pOriginalTagData, numBytesParsed);
-
- // copy new @value in place of current tag data
- union { uint32_t value; char valueBuffer[sizeof(uint32_t)]; } un;
- un.value = value;
- memcpy(newTagData + beginningTagDataLength, un.valueBuffer, sizeof(uint32_t));
-
- // skip to next tag (if tag for removal is last, return true)
- const char* pTagStorageType = pTagData - 1;
- if ( !Internal::SkipToNextTag(*pTagStorageType, pTagData, numBytesParsed) )
- return true;
-
- // copy everything from current tag (the next one after tag for removal) to end
- const unsigned int skippedDataLength = (numBytesParsed - beginningTagDataLength);
- const unsigned int endTagOffset = beginningTagDataLength + sizeof(uint32_t);
- const unsigned int endTagDataLength = originalTagDataLength - beginningTagDataLength - skippedDataLength;
- memcpy(newTagData + endTagOffset, pTagData, endTagDataLength);
-
- // ensure null-terminator
- newTagData[ endTagOffset + endTagDataLength + 1 ] = 0;
-
- // save new tag data
- TagData.assign(newTagData, endTagOffset + endTagDataLength);
- return true;
- }
-
- // tag not found, attempt AddTag
- else return AddTag(tag, type, value);
-}
-
-/*! \fn bool BamAlignment::EditTag(const std::string& tag, const std::string& type, const int32_t& value)
- \brief Edits a BAM tag field containing signed integer 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 NOT be "f", "Z", "H", or "B")
- \param value signed integer 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.
-*/
-bool BamAlignment::EditTag(const std::string& tag, const std::string& type, const int32_t& value) {
- return EditTag(tag, type, (const uint32_t&)value);
-}
-
-/*! \fn bool BamAlignment::EditTag(const std::string& tag, const std::string& type, const float& value)
- \brief Edits a BAM tag field containing floating-point 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 NOT be "Z", "H", or "B")
- \param value float 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.
-*/
-bool BamAlignment::EditTag(const std::string& tag, const std::string& type, const float& value) {
-
- // skip if core data not parsed
- if ( SupportData.HasCoreOnly ) return false;
-
- // validate tag/type size & that type is OK for float value
- if ( !Internal::IsValidSize(tag, type) ) return false;
- if ( type.at(0) == Constants::BAM_TAG_TYPE_STRING ||
- type.at(0) == Constants::BAM_TAG_TYPE_HEX ||
- type.at(0) == Constants::BAM_TAG_TYPE_ARRAY
- )
- {
- return false;
- }
-
- // localize the tag data
- char* pOriginalTagData = (char*)TagData.data();
- char* pTagData = pOriginalTagData;
- const unsigned int originalTagDataLength = TagData.size();
-
- unsigned int newTagDataLength = 0;
- unsigned int numBytesParsed = 0;
-
- // if tag found
- if ( Internal::FindTag(tag, pTagData, originalTagDataLength, numBytesParsed) ) {
-
- // make sure array is more than big enough
- char newTagData[originalTagDataLength + sizeof(value)];
-
- // copy original tag data up til desired tag
- const unsigned int beginningTagDataLength = numBytesParsed;
- newTagDataLength += beginningTagDataLength;
- memcpy(newTagData, pOriginalTagData, numBytesParsed);
-
- // copy new @value in place of current tag data
- union { float value; char valueBuffer[sizeof(float)]; } un;
- un.value = value;
- memcpy(newTagData + beginningTagDataLength, un.valueBuffer, sizeof(float));
-
- // skip to next tag (if tag for removal is last, return true)
- const char* pTagStorageType = pTagData - 1;
- if ( !Internal::SkipToNextTag(*pTagStorageType, pTagData, numBytesParsed) )
- return true;
-
- // copy everything from current tag (the next one after tag for removal) to end
- const unsigned int skippedDataLength = (numBytesParsed - beginningTagDataLength);
- const unsigned int endTagOffset = beginningTagDataLength + sizeof(float);
- const unsigned int endTagDataLength = originalTagDataLength - beginningTagDataLength - skippedDataLength;
- memcpy(newTagData + endTagOffset, pTagData, endTagDataLength);
-
- // ensure null-terminator
- newTagData[ endTagOffset + endTagDataLength + 1 ] = 0;
-
- // save new tag data
- TagData.assign(newTagData, endTagOffset + endTagDataLength);
- return true;
- }
-
- // tag not found, attempt AddTag
- else return AddTag(tag, type, value);
-}
-
-/*! \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.
-*/
-bool BamAlignment::EditTag(const std::string& tag, const std::vector<uint8_t>& values) {
-
- // can't do anything if TagData not parsed
- if ( SupportData.HasCoreOnly )
- return false;
-
- // remove existing tag if present
- if ( HasTag(tag) )
- RemoveTag(tag);
-
- // add tag record with new values
- return AddTag(tag, values);
-}
-
-/*! \fn bool EditTag(const std::string& tag, const std::vector<int8_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 int8_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.
-*/
-bool BamAlignment::EditTag(const std::string& tag, const std::vector<int8_t>& values) {
-
- // can't do anything if TagData not parsed
- if ( SupportData.HasCoreOnly )
- return false;
-
- // remove existing tag if present
- if ( HasTag(tag) )
- RemoveTag(tag);
-
- // add tag record with new values
- return AddTag(tag, values);
-}
-
-/*! \fn bool EditTag(const std::string& tag, const std::vector<uint16_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 uint16_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.
-*/
-bool BamAlignment::EditTag(const std::string& tag, const std::vector<uint16_t>& values) {
-
- // can't do anything if TagData not parsed
- if ( SupportData.HasCoreOnly )
- return false;
-
- // remove existing tag if present
- if ( HasTag(tag) )
- RemoveTag(tag);
-
- // add tag record with new values
- return AddTag(tag, values);
-}
-
-/*! \fn bool EditTag(const std::string& tag, const std::vector<int16_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 int16_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.
-*/
-bool BamAlignment::EditTag(const std::string& tag, const std::vector<int16_t>& values) {
-
- // can't do anything if TagData not parsed
- if ( SupportData.HasCoreOnly )
- return false;
-
- // remove existing tag if present
- if ( HasTag(tag) )
- RemoveTag(tag);
-
- // add tag record with new values
- return AddTag(tag, values);
-}
-
-/*! \fn bool EditTag(const std::string& tag, const std::vector<uint32_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 uint32_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.
-*/
-bool BamAlignment::EditTag(const std::string& tag, const std::vector<uint32_t>& values) {
-
- // can't do anything if TagData not parsed
- if ( SupportData.HasCoreOnly )
- return false;
-
- // remove existing tag if present
- if ( HasTag(tag) )
- RemoveTag(tag);
-
- // add tag record with new values
- return AddTag(tag, values);
-}
-
-/*! \fn bool EditTag(const std::string& tag, const std::vector<int32_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 int32_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.
-*/
-bool BamAlignment::EditTag(const std::string& tag, const std::vector<int32_t>& values) {
-
- // can't do anything if TagData not parsed
- if ( SupportData.HasCoreOnly )
- return false;
-
- // remove existing tag if present
- if ( HasTag(tag) )
- RemoveTag(tag);
-
- // add tag record with new values
- return AddTag(tag, values);
-}
-
-/*! \fn bool EditTag(const std::string& tag, const std::vector<float>& 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 float 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.
-*/
-bool BamAlignment::EditTag(const std::string& tag, const std::vector<float>& values) {
-
- // can't do anything if TagData not parsed
- if ( SupportData.HasCoreOnly )
- return false;
-
- // remove existing tag if present
- if ( HasTag(tag) )
- RemoveTag(tag);
-
- // add tag record with new values
- return AddTag(tag, values);
-}
-
-/*! \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
-*/
-bool BamAlignment::GetEditDistance(uint32_t& editDistance) const {
- return GetTag("NM", (uint32_t&)editDistance);
-}
-
-/*! \fn int BamAlignment::GetEndPosition(bool usePadded = false, bool zeroBased = true) const
- \brief Calculates alignment end position, based on starting position and CIGAR data.
-
- \param usePadded Inserted bases affect reported position. Default is false, so that reported
- position stays 'sync-ed' with reference coordinates.
- \param zeroBased Return (BAM standard) 0-based coordinate. Setting this to false can be useful
- when using BAM data with half-open formats (e.g. BED).
-
- \return alignment end position
-*/
-int BamAlignment::GetEndPosition(bool usePadded, bool zeroBased) const {
-
- // initialize alignment end to starting position
- int alignEnd = Position;
-
- // iterate over cigar operations
- vector<CigarOp>::const_iterator cigarIter = CigarData.begin();
- vector<CigarOp>::const_iterator cigarEnd = CigarData.end();
- for ( ; cigarIter != cigarEnd; ++cigarIter) {
- const char cigarType = (*cigarIter).Type;
- const uint32_t& cigarLength = (*cigarIter).Length;
-
- if ( cigarType == Constants::BAM_CIGAR_MATCH_CHAR ||
- cigarType == Constants::BAM_CIGAR_DEL_CHAR ||
- cigarType == Constants::BAM_CIGAR_REFSKIP_CHAR )
- alignEnd += cigarLength;
- else if ( usePadded && cigarType == Constants::BAM_CIGAR_INS_CHAR )
- alignEnd += cigarLength;
- }
-
- // adjust for zero-based coordinates, if requested
- if ( zeroBased ) alignEnd -= 1;
-
- // return result
- return alignEnd;
-}
-
-/*! \fn bool BamAlignment::GetReadGroup(std::string& readGroup) const
- \brief Retrieves value of read group tag ("RG").
-
- \deprecated Instead use BamAlignment::GetTag()
- \code
- BamAlignment::GetTag("RG", readGroup);
- \endcode
-
- \param readGroup destination for retrieved value
-
- \return \c true if found
-*/
-bool BamAlignment::GetReadGroup(std::string& readGroup) const {
- return GetTag("RG", readGroup);
-}
-
-/*! \fn bool BamAlignment::GetTag(const std::string& tag, std::string& destination) const
- \brief Retrieves the string value associated with a BAM tag.
-
- \param tag 2-character tag name
- \param destination destination for retrieved value
-
- \return \c true if found
-*/
-bool BamAlignment::GetTag(const std::string& tag, std::string& destination) const {
-
- // make sure tag data exists
- if ( SupportData.HasCoreOnly || TagData.empty() )
- return false;
-
- // localize the tag data
- char* pTagData = (char*)TagData.data();
- const unsigned int tagDataLength = TagData.size();
- unsigned int numBytesParsed = 0;
-
- // if tag found
- if ( Internal::FindTag(tag, pTagData, tagDataLength, numBytesParsed) ) {
- const unsigned int dataLength = strlen(pTagData);
- destination.clear();
- destination.resize(dataLength);
- memcpy( (char*)destination.data(), pTagData, dataLength );
- return true;
- }
-
- // tag not found, return failure
- return false;
-}
-
-/*! \fn bool BamAlignment::GetTag(const std::string& tag, uint32_t& destination) const
- \brief Retrieves the unsigned integer value associated with a BAM tag.
-
- \param tag 2-character tag name
- \param destination destination for retrieved value
-
- \return \c true if found
-*/
-bool BamAlignment::GetTag(const std::string& tag, uint32_t& destination) const {
-
- // make sure tag data exists
- if ( SupportData.HasCoreOnly || TagData.empty() )
- return false;
-
- // localize the tag data
- char* pTagData = (char*)TagData.data();
- const unsigned int tagDataLength = TagData.size();
- unsigned int numBytesParsed = 0;
-
- // if tag found
- if ( Internal::FindTag(tag, pTagData, tagDataLength, numBytesParsed) ) {
-
- // determine data byte-length
- const char type = *(pTagData - 1);
- int destinationLength = 0;
- switch (type) {
-
- // 1 byte data
- case (Constants::BAM_TAG_TYPE_ASCII) :
- case (Constants::BAM_TAG_TYPE_INT8) :
- case (Constants::BAM_TAG_TYPE_UINT8) :
- destinationLength = 1;
- break;
-
- // 2 byte data
- case (Constants::BAM_TAG_TYPE_INT16) :
- case (Constants::BAM_TAG_TYPE_UINT16) :
- destinationLength = 2;
- break;
-
- // 4 byte data
- case (Constants::BAM_TAG_TYPE_INT32) :
- case (Constants::BAM_TAG_TYPE_UINT32) :
- destinationLength = 4;
- break;
-
- // unsupported type for integer destination (float or var-length strings)
- case (Constants::BAM_TAG_TYPE_FLOAT) :
- case (Constants::BAM_TAG_TYPE_STRING) :
- case (Constants::BAM_TAG_TYPE_HEX) :
- case (Constants::BAM_TAG_TYPE_ARRAY) :
- cerr << "BamAlignment ERROR: cannot store tag of type " << type
- << " in integer destination" << endl;
- return false;
-
- // unknown tag type
- default:
- cerr << "BamAlignment ERROR: unknown tag type encountered: "
- << type << endl;
- return false;
- }
-
- // store in destination
- destination = 0;
- memcpy(&destination, pTagData, destinationLength);
- return true;
- }
-
- // tag not found, return failure
- return false;
-}
-
-/*! \fn bool BamAlignment::GetTag(const std::string& tag, int32_t& destination) const
- \brief Retrieves the signed integer value associated with a BAM tag.
-
- \param tag 2-character tag name
- \param destination destination for retrieved value
-
- \return \c true if found
-*/
-bool BamAlignment::GetTag(const std::string& tag, int32_t& destination) const {
- return GetTag(tag, (uint32_t&)destination);
-}
-
-/*! \fn bool BamAlignment::GetTag(const std::string& tag, float& destination) const
- \brief Retrieves the floating-point value associated with a BAM tag.
-
- \param tag 2-character tag name
- \param destination destination for retrieved value
-
- \return \c true if found
-*/
-bool BamAlignment::GetTag(const std::string& tag, float& destination) const {
-
- // make sure tag data exists
- if ( SupportData.HasCoreOnly || TagData.empty() )
- return false;
-
- // localize the tag data
- char* pTagData = (char*)TagData.data();
- const unsigned int tagDataLength = TagData.size();
- unsigned int numBytesParsed = 0;
-
- // if tag found
- if ( Internal::FindTag(tag, pTagData, tagDataLength, numBytesParsed) ) {
-
- // determine data byte-length
- const char type = *(pTagData - 1);
- int destinationLength = 0;
- switch (type) {
-
- // 1 byte data
- case (Constants::BAM_TAG_TYPE_ASCII) :
- case (Constants::BAM_TAG_TYPE_INT8) :
- case (Constants::BAM_TAG_TYPE_UINT8) :
- destinationLength = 1;
- break;
-
- // 2 byte data
- case (Constants::BAM_TAG_TYPE_INT16) :
- case (Constants::BAM_TAG_TYPE_UINT16) :
- destinationLength = 2;
- break;
-
- // 4 byte data
- case (Constants::BAM_TAG_TYPE_FLOAT) :
- case (Constants::BAM_TAG_TYPE_INT32) :
- case (Constants::BAM_TAG_TYPE_UINT32) :
- destinationLength = 4;
- break;
-
- // unsupported type (var-length strings)
- case (Constants::BAM_TAG_TYPE_STRING) :
- case (Constants::BAM_TAG_TYPE_HEX) :
- case (Constants::BAM_TAG_TYPE_ARRAY) :
- cerr << "BamAlignment ERROR: cannot store tag of type " << type
- << " in float destination" << endl;
- return false;
-
- // unknown tag type
- default:
- cerr << "BamAlignment ERROR: unknown tag type encountered: "
- << type << endl;
- return false;
- }
-
- // store in destination
- destination = 0.0;
- memcpy(&destination, pTagData, destinationLength);
- return true;
- }
-
- // tag not found, return failure
- return false;
-}
-
-/*! \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
-
- \param tag 2-character tag name
- \param destination destination for retrieved data
-
- \return \c true if found
-*/
-bool BamAlignment::GetTag(const std::string& tag, std::vector<uint32_t>& destination) const {
-
- // make sure tag data exists
- if ( SupportData.HasCoreOnly || TagData.empty() )
- return false;
-
- // localize the tag data
- char* pTagData = (char*)TagData.data();
- const unsigned int tagDataLength = TagData.size();
- unsigned int numBytesParsed = 0;
-
- // return false if tag not found
- if ( !Internal::FindTag(tag, pTagData, tagDataLength, numBytesParsed) )
- return false;
-
- // check that tag is array type
- const char tagType = *(pTagData - 1);
- if ( tagType != Constants::BAM_TAG_TYPE_ARRAY ) {
- cerr << "BamAlignment ERROR: Cannot store non-array data from tag: "
- << tag << " in array destination" << endl;
- return false;
- }
-
- // calculate length of each element in tag's array
- const char elementType = *pTagData;
- ++pTagData;
- int elementLength = 0;
- switch ( elementType ) {
- case (Constants::BAM_TAG_TYPE_ASCII) :
- case (Constants::BAM_TAG_TYPE_INT8) :
- case (Constants::BAM_TAG_TYPE_UINT8) :
- elementLength = sizeof(uint8_t);
- break;
-
- case (Constants::BAM_TAG_TYPE_INT16) :
- case (Constants::BAM_TAG_TYPE_UINT16) :
- elementLength = sizeof(uint16_t);
- break;
-
- case (Constants::BAM_TAG_TYPE_INT32) :
- case (Constants::BAM_TAG_TYPE_UINT32) :
- elementLength = sizeof(uint32_t);
- break;
-
- // unsupported type for integer destination (float or var-length data)
- case (Constants::BAM_TAG_TYPE_FLOAT) :
- case (Constants::BAM_TAG_TYPE_STRING) :
- case (Constants::BAM_TAG_TYPE_HEX) :
- case (Constants::BAM_TAG_TYPE_ARRAY) :
- cerr << "BamAlignment ERROR: array element type: " << elementType
- << " cannot be stored in integer value" << endl;
- return false;
-
- // unknown tag type
- default:
- cerr << "BamAlignment ERROR: unknown element type encountered: "
- << elementType << endl;
- return false;
- }
-
- // get number of elements
- int32_t numElements;
- memcpy(&numElements, pTagData, sizeof(int32_t));
- pTagData += 4;
- destination.clear();
- destination.reserve(numElements);
-
- // read in elements
- uint32_t value;
- for ( int i = 0 ; i < numElements; ++i ) {
- memcpy(&value, pTagData, sizeof(uint32_t));
- pTagData += sizeof(uint32_t);
- destination.push_back(value);
- }
-
- // return success