]> git.donarmstrong.com Git - bamtools.git/blob - src/toolkit/bamtools_revert.cpp
Fixed: regression in convert tool - SAM tags contained unreadable chars for int8...
[bamtools.git] / src / toolkit / bamtools_revert.cpp
1 // ***************************************************************************
2 // bamtools_revert.cpp (c) 2010 Derek Barnett, Alistair Ward
3 // Marth Lab, Department of Biology, Boston College
4 // ---------------------------------------------------------------------------
5 // Last modified: 7 April 2011
6 // ---------------------------------------------------------------------------
7 // Removes duplicate marks and restores original base qualities
8 // ***************************************************************************
9
10 #include "bamtools_revert.h"
11
12 #include <api/BamReader.h>
13 #include <api/BamWriter.h>
14 #include <utils/bamtools_options.h>
15 #include <utils/bamtools_utilities.h>
16 using namespace BamTools;
17
18 #include <iostream>
19 #include <string>
20 using namespace std;
21
22 namespace BamTools {
23
24 static const string OQ_TAG = "OQ";
25
26 } // namespace BamTools;
27
28 // ---------------------------------------------
29 // RevertSettings implementation
30
31 struct RevertTool::RevertSettings {
32
33     // flags
34     bool HasInput;
35     bool HasOutput;
36     bool IsForceCompression;
37     bool IsKeepDuplicateFlag;
38     bool IsKeepQualities;
39
40     // filenames
41     string InputFilename;
42     string OutputFilename;
43     
44     // constructor
45     RevertSettings(void)
46         : HasInput(false)
47         , HasOutput(false)
48         , IsForceCompression(false)
49         , IsKeepDuplicateFlag(false)
50         , IsKeepQualities(false)
51         , InputFilename(Options::StandardIn())
52         , OutputFilename(Options::StandardOut())
53     { }
54 };  
55
56 // ---------------------------------------------
57 // RevertToolPrivate implementation
58
59 struct RevertTool::RevertToolPrivate {
60   
61     // ctor & dtor
62     public:
63         RevertToolPrivate(RevertTool::RevertSettings* settings)
64             : m_settings(settings)
65         { }
66         ~RevertToolPrivate(void) { }
67   
68     // 'public' interface
69     public:
70         bool Run(void);
71         
72     // internal methods
73     private:
74         void RevertAlignment(BamAlignment& al);
75         
76     // data members
77     private:
78         RevertTool::RevertSettings* m_settings;
79 };
80
81 // 'reverts' a BAM alignment
82 // default behavior (for now) is:
83 //   1 - replace Qualities with OQ contents
84 //   2 - clear IsDuplicate flag
85 // can override default behavior using command line options
86 void RevertTool::RevertToolPrivate::RevertAlignment(BamAlignment& al) {
87
88     // replace Qualities with OQ contents, if requested
89     if ( !m_settings->IsKeepQualities ) {
90         string originalQualities;
91         if ( al.GetTag(OQ_TAG, originalQualities) ) {
92             al.Qualities = originalQualities;
93             al.RemoveTag(OQ_TAG);
94         }
95     }
96
97     // clear duplicate flag, if requested
98     if ( !m_settings->IsKeepDuplicateFlag )
99         al.SetIsDuplicate(false);
100 }
101
102 bool RevertTool::RevertToolPrivate::Run(void) {
103   
104     // opens the BAM file without checking for indexes
105     BamReader reader;
106     if ( !reader.Open(m_settings->InputFilename) ) {
107         cerr << "bamtools revert ERROR: could not open " << m_settings->InputFilename
108              << " for reading... Aborting." << endl;
109         return false;
110     }
111
112     // get BAM file metadata
113     const string& headerText = reader.GetHeaderText();
114     const RefVector& references = reader.GetReferenceData();
115     
116     // determine compression mode for BamWriter
117     bool writeUncompressed = ( m_settings->OutputFilename == Options::StandardOut() &&
118                               !m_settings->IsForceCompression );
119     BamWriter::CompressionMode compressionMode = BamWriter::Compressed;
120     if ( writeUncompressed ) compressionMode = BamWriter::Uncompressed;
121
122     // open BamWriter
123     BamWriter writer;
124     writer.SetCompressionMode(compressionMode);
125     if ( !writer.Open(m_settings->OutputFilename, headerText, references) ) {
126         cerr << "bamtools revert ERROR: could not open " << m_settings->OutputFilename
127              << " for writing... Aborting." << endl;
128         reader.Close();
129         return false;
130     }
131
132     // plow through file, reverting alignments
133     BamAlignment al;
134     while ( reader.GetNextAlignment(al) ) {
135         RevertAlignment(al);
136         writer.SaveAlignment(al);
137     }
138     
139     // clean and exit
140     reader.Close();
141     writer.Close();
142     return true; 
143 }
144
145 // ---------------------------------------------
146 // RevertTool implementation
147
148 RevertTool::RevertTool(void)
149     : AbstractTool()
150     , m_settings(new RevertSettings)
151     , m_impl(0)
152 {
153     // set program details
154     Options::SetProgramInfo("bamtools revert", "removes duplicate marks and restores original (non-recalibrated) base qualities", "[-in <filename> -in <filename> ...] [-out <filename> | [-forceCompression]] [revertOptions]");
155     
156     // set up options 
157     OptionGroup* IO_Opts = Options::CreateOptionGroup("Input & Output");
158     Options::AddValueOption("-in",  "BAM filename", "the input BAM file",  "", m_settings->HasInput,  m_settings->InputFilename,  IO_Opts, Options::StandardIn());
159     Options::AddValueOption("-out", "BAM filename", "the output BAM file", "", m_settings->HasOutput, m_settings->OutputFilename, IO_Opts, Options::StandardOut());
160     Options::AddOption("-forceCompression", "if results are sent to stdout (like when piping to another tool), default behavior is to leave output uncompressed. Use this flag to override and force compression", m_settings->IsForceCompression, IO_Opts);
161
162     OptionGroup* RevertOpts = Options::CreateOptionGroup("Revert Options");
163     Options::AddOption("-keepDuplicate", "keep duplicates marked", m_settings->IsKeepDuplicateFlag, RevertOpts);
164     Options::AddOption("-keepQualities", "keep base qualities (do not replace with OQ contents)", m_settings->IsKeepQualities, RevertOpts);
165 }
166
167 RevertTool::~RevertTool(void) {
168
169     delete m_settings;
170     m_settings = 0;
171     
172     delete m_impl;
173     m_impl = 0;
174 }
175
176 int RevertTool::Help(void) {
177     Options::DisplayHelp();
178     return 0;
179 }
180
181 int RevertTool::Run(int argc, char* argv[]) {
182   
183     // parse command line arguments
184     Options::Parse(argc, argv, 1);
185
186     // intialize RevertTool with settings
187     m_impl = new RevertToolPrivate(m_settings);
188     
189     // run RevertTool, return success/fail
190     if ( m_impl->Run() )
191         return 0;
192     else
193         return 1;
194 }