1 // ***************************************************************************
2 // bamtools_sam.cpp (c) 2010 Derek Barnett, Erik Garrison
3 // Marth Lab, Department of Biology, Boston College
4 // All rights reserved.
5 // ---------------------------------------------------------------------------
6 // Last modified: 2 June 2010
7 // ---------------------------------------------------------------------------
8 // Prints a BAM file in the text-based SAM format.
9 // ***************************************************************************
16 #include "bamtools_sam.h"
17 #include "bamtools_options.h"
18 #include "BamReader.h"
22 using namespace BamTools;
24 static RefVector references;
26 // ---------------------------------------------
27 // print BamAlignment in SAM format
29 void PrintSAM(const BamAlignment& a) {
32 // <QNAME> <FLAG> <RNAME> <POS> <MAPQ> <CIGAR> <MRNM> <MPOS> <ISIZE> <SEQ> <QUAL> [ <TAG>:<VTYPE>:<VALUE> [...] ]
36 // write name & alignment flag
37 cout << a.Name << "\t" << a.AlignmentFlag << "\t";
39 // write reference name
40 if ( (a.RefID >= 0) && (a.RefID < (int)references.size()) ) cout << references[a.RefID].RefName << "\t";
43 // write position & map quality
44 cout << a.Position+1 << "\t" << a.MapQuality << "\t";
47 const vector<CigarOp>& cigarData = a.CigarData;
48 if ( cigarData.empty() ) cout << "*\t";
50 vector<CigarOp>::const_iterator cigarIter = cigarData.begin();
51 vector<CigarOp>::const_iterator cigarEnd = cigarData.end();
52 for ( ; cigarIter != cigarEnd; ++cigarIter ) {
53 const CigarOp& op = (*cigarIter);
54 cout << op.Length << op.Type;
59 // write mate reference name, mate position, & insert size
60 if ( a.IsPaired() && (a.MateRefID >= 0) && (a.MateRefID < (int)references.size()) ) {
61 if ( a.MateRefID == a.RefID ) cout << "=\t";
62 else cout << references[a.MateRefID].RefName << "\t";
63 cout << a.MatePosition+1 << "\t" << a.InsertSize << "\t";
65 else cout << "*\t0\t0\t";
68 if ( a.QueryBases.empty() ) cout << "*\t";
69 else cout << a.QueryBases << "\t";
72 if ( a.Qualities.empty() ) cout << "*";
73 else cout << a.Qualities;
76 const char* tagData = a.TagData.c_str();
77 const size_t tagDataLength = a.TagData.length();
79 while ( index < tagDataLength ) {
82 cout << "\t" << a.TagData.substr(index, 2) << ":";
86 char type = a.TagData.at(index);
91 cout << "A:" << tagData[index];
96 cout << "i:" << atoi(&tagData[index]);
101 cout << "i:" << atoi(&tagData[index]);
106 cout << "i:" << BgzfData::UnpackUnsignedShort(&tagData[index]);
111 cout << "i:" << BgzfData::UnpackSignedShort(&tagData[index]);
116 cout << "i:" << BgzfData::UnpackUnsignedInt(&tagData[index]);
121 cout << "i:" << BgzfData::UnpackSignedInt(&tagData[index]);
126 cout << "f:" << BgzfData::UnpackFloat(&tagData[index]);
131 cout << "d:" << BgzfData::UnpackDouble(&tagData[index]);
138 while (tagData[index]) {
139 cout << tagData[index];
147 // write stream to stdout
148 cout << sb.str() << endl;
151 // ---------------------------------------------
152 // SamSettings implementation
154 struct SamTool::SamSettings {
157 bool HasInputBamFilename;
158 bool HasMaximumOutput;
159 bool IsOmittingHeader;
162 string InputBamFilename;
169 : HasInputBamFilename(false)
170 , HasMaximumOutput(false)
171 , IsOmittingHeader(false)
172 , InputBamFilename(Options::StandardIn())
176 // ---------------------------------------------
177 // SamTool implementation
179 SamTool::SamTool(void)
181 , m_settings(new SamSettings)
183 // set program details
184 Options::SetProgramInfo("bamtools sam", "prints BAM file in SAM text format", "-in <filename>");
187 OptionGroup* IO_Opts = Options::CreateOptionGroup("Input & Output");
188 Options::AddValueOption("-in", "BAM filename", "the input BAM file", "", m_settings->HasInputBamFilename, m_settings->InputBamFilename, IO_Opts, Options::StandardIn());
190 OptionGroup* FilterOpts = Options::CreateOptionGroup("Filters");
191 Options::AddOption("-noheader", "omit the SAM header from output", m_settings->IsOmittingHeader, FilterOpts);
192 Options::AddValueOption("-num", "N", "maximum number of alignments to output", "", m_settings->HasMaximumOutput, m_settings->MaximumOutput, FilterOpts);
195 SamTool::~SamTool(void) {
200 int SamTool::Help(void) {
201 Options::DisplayHelp();
205 int SamTool::Run(int argc, char* argv[]) {
207 // parse command line arguments
208 Options::Parse(argc, argv, 1);
210 // open our BAM reader
212 reader.Open(m_settings->InputBamFilename);
214 // if header desired, retrieve and print to stdout
215 if ( !m_settings->IsOmittingHeader ) {
216 string header = reader.GetHeaderText();
217 cout << header << endl;
220 // store reference data
221 references = reader.GetReferenceData();
223 // print all alignments to stdout in SAM format
224 if ( !m_settings->HasMaximumOutput ) {
226 while( reader.GetNextAlignment(ba) ) {
231 // print first N alignments to stdout in SAM format
234 int alignmentsPrinted = 0;
235 while ( reader.GetNextAlignment(ba) && (alignmentsPrinted < m_settings->MaximumOutput) ) {