]> git.donarmstrong.com Git - bamtools.git/blobdiff - src/toolkit/bamtools_convert.cpp
Fixed: regression in convert tool - SAM tags contained unreadable chars for int8...
[bamtools.git] / src / toolkit / bamtools_convert.cpp
index cc32e2c9a2f90e7e975c84f8983613baf4a8a832..0e1743ffcba56a1859fbe946c3a345f890ac037a 100644 (file)
@@ -1,9 +1,8 @@
 // ***************************************************************************
 // bamtools_convert.cpp (c) 2010 Derek Barnett, Erik Garrison
 // Marth Lab, Department of Biology, Boston College
-// All rights reserved.
 // ---------------------------------------------------------------------------
-// Last modified: 21 March 2011
+// Last modified: 11 November 2012
 // ---------------------------------------------------------------------------
 // Converts between BAM and a number of other formats
 // ***************************************************************************
@@ -27,46 +26,46 @@ using namespace std;
   
 namespace BamTools { 
   
-    // ---------------------------------------------
-    // ConvertTool constants
-  
-    // supported conversion format command-line names
-    static const string FORMAT_BED    = "bed";
-    static const string FORMAT_FASTA  = "fasta";
-    static const string FORMAT_FASTQ  = "fastq";
-    static const string FORMAT_JSON   = "json";
-    static const string FORMAT_SAM    = "sam";
-    static const string FORMAT_PILEUP = "pileup";
-    static const string FORMAT_YAML   = "yaml";
-
-    // other constants
-    static const unsigned int FASTA_LINE_MAX = 50;
-    
-    // ---------------------------------------------
-    // ConvertPileupFormatVisitor declaration
-    
-    class ConvertPileupFormatVisitor : public PileupVisitor {
-      
-        // ctor & dtor
-        public:
-            ConvertPileupFormatVisitor(const RefVector& references, 
-                                       const string& fastaFilename,
-                                       const bool isPrintingMapQualities,
-                                       ostream* out);
-            ~ConvertPileupFormatVisitor(void);
-      
-        // PileupVisitor interface implementation
-        public:
-            void Visit(const PileupPosition& pileupData);
-            
-        // data members
-        private:
-            Fasta     m_fasta;
-            bool      m_hasFasta;
-            bool      m_isPrintingMapQualities;
-            ostream*  m_out;
-            RefVector m_references;
-    };
+// ---------------------------------------------
+// ConvertTool constants
+
+// supported conversion format command-line names
+static const string FORMAT_BED    = "bed";
+static const string FORMAT_FASTA  = "fasta";
+static const string FORMAT_FASTQ  = "fastq";
+static const string FORMAT_JSON   = "json";
+static const string FORMAT_SAM    = "sam";
+static const string FORMAT_PILEUP = "pileup";
+static const string FORMAT_YAML   = "yaml";
+
+// other constants
+static const unsigned int FASTA_LINE_MAX = 50;
+
+// ---------------------------------------------
+// ConvertPileupFormatVisitor declaration
+
+class ConvertPileupFormatVisitor : public PileupVisitor {
+
+    // ctor & dtor
+    public:
+        ConvertPileupFormatVisitor(const RefVector& references,
+                                   const string& fastaFilename,
+                                   const bool isPrintingMapQualities,
+                                   ostream* out);
+        ~ConvertPileupFormatVisitor(void);
+
+    // PileupVisitor interface implementation
+    public:
+        void Visit(const PileupPosition& pileupData);
+
+    // data members
+    private:
+        Fasta     m_fasta;
+        bool      m_hasFasta;
+        bool      m_isPrintingMapQualities;
+        ostream*  m_out;
+        RefVector m_references;
+};
     
 } // namespace BamTools
   
@@ -75,7 +74,7 @@ namespace BamTools {
 
 struct ConvertTool::ConvertSettings {
 
-    // flags
+    // flag
     bool HasInput;
     bool HasOutput;
     bool HasFormat;
@@ -116,8 +115,12 @@ struct ConvertTool::ConvertToolPrivate {
   
     // ctor & dtor
     public:
-        ConvertToolPrivate(ConvertTool::ConvertSettings* settings);
-        ~ConvertToolPrivate(void);
+        ConvertToolPrivate(ConvertTool::ConvertSettings* settings)
+            : m_settings(settings)
+            , m_out(cout.rdbuf())
+        { }
+
+        ~ConvertToolPrivate(void) { }
     
     // interface
     public:
@@ -142,13 +145,6 @@ struct ConvertTool::ConvertToolPrivate {
         ostream m_out;
 };
 
-ConvertTool::ConvertToolPrivate::ConvertToolPrivate(ConvertTool::ConvertSettings* settings)
-    : m_settings(settings)
-    , m_out(cout.rdbuf()) // default output to cout
-{ }
-
-ConvertTool::ConvertToolPrivate::~ConvertToolPrivate(void) { }
-
 bool ConvertTool::ConvertToolPrivate::Run(void) {
  
     // ------------------------------------
@@ -281,7 +277,7 @@ void ConvertTool::ConvertToolPrivate::PrintBed(const BamAlignment& a) {
 
     m_out << m_references.at(a.RefID).RefName << "\t"
           << a.Position << "\t"
-          << a.GetEndPosition() + 1 << "\t"
+          << a.GetEndPosition() << "\t"
           << a.Name << "\t"
           << a.MapQuality << "\t"
           << (a.IsReverseStrand() ? "-" : "+") << endl;
@@ -298,7 +294,7 @@ void ConvertTool::ConvertToolPrivate::PrintFasta(const BamAlignment& a) {
     // N.B. - QueryBases are reverse-complemented if aligned to reverse strand
   
     // print header
-    m_out << "> " << a.Name << endl;
+    m_out << ">" << a.Name << endl;
     
     // handle reverse strand alignment - bases 
     string sequence = a.QueryBases;
@@ -400,7 +396,7 @@ void ConvertTool::ConvertToolPrivate::PrintJson(const BamAlignment& a) {
         m_out << "\"queryBases\":\"" << a.QueryBases << "\",";
     
     // write qualities
-    if ( !a.Qualities.empty() ) {
+    if ( !a.Qualities.empty() && a.Qualities.at(0) != (char)0xFF ) {
         string::const_iterator s = a.Qualities.begin();
         m_out << "\"qualities\":[" << static_cast<short>(*s) - 33;
         ++s;
@@ -438,9 +434,15 @@ void ConvertTool::ConvertToolPrivate::PrintJson(const BamAlignment& a) {
                     ++index; 
                     break;
                 
-                case (Constants::BAM_TAG_TYPE_INT8)  :
+                case (Constants::BAM_TAG_TYPE_INT8) :
+                    // force value into integer-type (instead of char value)
+                    m_out << static_cast<int16_t>(tagData[index]);
+                    ++index;
+                    break;
+
                 case (Constants::BAM_TAG_TYPE_UINT8) :
-                    m_out << (int)tagData[index]; 
+                    // force value into integer-type (instead of char value)
+                    m_out << static_cast<uint16_t>(tagData[index]);
                     ++index; 
                     break;
                 
@@ -501,8 +503,8 @@ void ConvertTool::ConvertToolPrivate::PrintSam(const BamAlignment& a) {
     // <QNAME> <FLAG> <RNAME> <POS> <MAPQ> <CIGAR> <MRNM> <MPOS> <ISIZE> <SEQ> <QUAL> [ <TAG>:<VTYPE>:<VALUE> [...] ]
   
     // write name & alignment flag
-    m_out << a.Name << "\t" << a.AlignmentFlag << "\t";
-    
+   m_out << a.Name << "\t" << a.AlignmentFlag << "\t";
+
     // write reference name
     if ( (a.RefID >= 0) && (a.RefID < (int)m_references.size()) ) 
         m_out << m_references[a.RefID].RefName << "\t";
@@ -530,7 +532,7 @@ void ConvertTool::ConvertToolPrivate::PrintSam(const BamAlignment& a) {
         if ( a.MateRefID == a.RefID )
             m_out << "=\t";
         else
-            m_out << m_references[a.MateRefID].RefName << "\t";
+           m_out << m_references[a.MateRefID].RefName << "\t";
         m_out << a.MatePosition+1 << "\t" << a.InsertSize << "\t";
     } 
     else
@@ -543,7 +545,7 @@ void ConvertTool::ConvertToolPrivate::PrintSam(const BamAlignment& a) {
         m_out << a.QueryBases << "\t";
     
     // write qualities
-    if ( a.Qualities.empty() )
+    if ( a.Qualities.empty() || (a.Qualities.at(0) == (char)0xFF) )
         m_out << "*";
     else
         m_out << a.Qualities;
@@ -569,9 +571,15 @@ void ConvertTool::ConvertToolPrivate::PrintSam(const BamAlignment& a) {
                 ++index;
                 break;
 
-            case (Constants::BAM_TAG_TYPE_INT8)  :
+            case (Constants::BAM_TAG_TYPE_INT8) :
+                // force value into integer-type (instead of char value)
+                m_out << "i:" << static_cast<int16_t>(tagData[index]);
+                ++index;
+                break;
+
             case (Constants::BAM_TAG_TYPE_UINT8) :
-                m_out << "i:" << (int)tagData[index];
+                // force value into integer-type (instead of char value)
+                m_out << "i:" << static_cast<uint16_t>(tagData[index]);
                 ++index;
                 break;
 
@@ -600,7 +608,7 @@ void ConvertTool::ConvertToolPrivate::PrintSam(const BamAlignment& a) {
                 index += sizeof(float);
                 break;
 
-            case (Constants::BAM_TAG_TYPE_HEX)    :
+            case (Constants::BAM_TAG_TYPE_HEX)    : // fall-through
             case (Constants::BAM_TAG_TYPE_STRING) :
                 m_out << type << ":";
                 while (tagData[index]) {
@@ -611,7 +619,7 @@ void ConvertTool::ConvertToolPrivate::PrintSam(const BamAlignment& a) {
                 break;
         }
 
-        if ( tagData[index] == '\0'
+        if ( tagData[index] == '\0' )
             break;
     }
 
@@ -713,6 +721,7 @@ ConvertTool::ConvertTool(void)
 }
 
 ConvertTool::~ConvertTool(void) {
+
     delete m_settings;
     m_settings = 0;
     
@@ -730,9 +739,10 @@ int ConvertTool::Run(int argc, char* argv[]) {
     // parse command line arguments
     Options::Parse(argc, argv, 1);
     
-    // run internal ConvertTool implementation, return success/fail
+    // initialize ConvertTool with settings
     m_impl = new ConvertToolPrivate(m_settings);
     
+    // run ConvertTool, return success/fail
     if ( m_impl->Run() ) 
         return 0;
     else