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