]> git.donarmstrong.com Git - bamtools.git/blobdiff - src/toolkit/bamtools_split.cpp
Added '-tagPrefix' option to 'bamtools split' tool. (issue #75)
[bamtools.git] / src / toolkit / bamtools_split.cpp
index 4575d8596cc9c1dc8b808e8690f3ca2bfbb2d08d..6425e9529a63da8cb2f99bcab8ead6b0c29f8352 100644 (file)
@@ -2,7 +2,7 @@
 // bamtools_split.cpp (c) 2010 Derek Barnett, Erik Garrison
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 7 April 2011 (DB)
+// Last modified: 24 July 2013 (DB)
 // ---------------------------------------------------------------------------
 // Splits a BAM file on user-specified property, creating a new BAM output
 // file for each value found
@@ -33,6 +33,7 @@ static const string SPLIT_UNMAPPED_TOKEN  = ".UNMAPPED";
 static const string SPLIT_PAIRED_TOKEN    = ".PAIRED_END";
 static const string SPLIT_SINGLE_TOKEN    = ".SINGLE_END";
 static const string SPLIT_REFERENCE_TOKEN = ".REF_";
+static const string SPLIT_TAG_TOKEN       = ".TAG_";
 
 string GetTimestampString(void) {
 
@@ -69,6 +70,8 @@ struct SplitTool::SplitSettings {
     // flags
     bool HasInputFilename;
     bool HasCustomOutputStub;
+    bool HasCustomRefPrefix;
+    bool HasCustomTagPrefix;
     bool IsSplittingMapped;
     bool IsSplittingPaired;
     bool IsSplittingReference;
@@ -76,6 +79,8 @@ struct SplitTool::SplitSettings {
     
     // string args
     string CustomOutputStub;
+    string CustomRefPrefix;
+    string CustomTagPrefix;
     string InputFilename;
     string TagToSplit;
     
@@ -83,11 +88,15 @@ struct SplitTool::SplitSettings {
     SplitSettings(void)
         : HasInputFilename(false)
         , HasCustomOutputStub(false)
+        , HasCustomRefPrefix(false)
+        , HasCustomTagPrefix(false)
         , IsSplittingMapped(false)
         , IsSplittingPaired(false)
         , IsSplittingReference(false)
         , IsSplittingTag(false)
         , CustomOutputStub("")
+        , CustomRefPrefix("")
+        , CustomTagPrefix("")
         , InputFilename(Options::StandardIn())
         , TagToSplit("")
     { } 
@@ -298,6 +307,16 @@ bool SplitTool::SplitToolPrivate::SplitReference(void) {
     map<int32_t, BamWriter*> outputFiles;
     map<int32_t, BamWriter*>::iterator writerIter;
     
+    // determine reference prefix
+    string refPrefix = SPLIT_REFERENCE_TOKEN;
+    if ( m_settings->HasCustomRefPrefix )
+        refPrefix = m_settings->CustomRefPrefix;
+
+    // make sure prefix starts with '.'
+    const size_t dotFound = refPrefix.find('.');
+    if ( dotFound != 0 )
+        refPrefix = string(".") + refPrefix;
+
     // iterate through alignments
     BamAlignment al;
     BamWriter* writer;
@@ -311,9 +330,17 @@ bool SplitTool::SplitToolPrivate::SplitReference(void) {
         // if no writer associated with this value
         if ( writerIter == outputFiles.end() ) {
         
+            // fetch reference name for ID
+            string refName;
+            if ( currentRefId == -1 )
+                refName = "unmapped";
+            else
+                refName = m_references.at(currentRefId).RefName;
+
+            // construct new output filename
+            const string outputFilename = m_outputFilenameStub + refPrefix + refName + ".bam";
+
             // open new BamWriter
-            const string refName = m_references.at(currentRefId).RefName;
-            const string outputFilename = m_outputFilenameStub + SPLIT_REFERENCE_TOKEN + refName + ".bam";
             writer = new BamWriter;
             if ( !writer->Open(outputFilename, m_header, m_references) ) {
                 cerr << "bamtools split ERROR: could not open " << outputFilename
@@ -373,9 +400,13 @@ bool SplitTool::SplitToolPrivate::SplitTag(void) {
             case (Constants::BAM_TAG_TYPE_STRING) :
             case (Constants::BAM_TAG_TYPE_HEX)    :
                 return SplitTagImpl<string>(al);
+
+            case (Constants::BAM_TAG_TYPE_ARRAY) :
+                cerr << "bamtools split ERROR: array tag types are not supported" << endl;
+                return false;
           
             default:
-                fprintf(stderr, "bamtools split ERROR: unknown tag type encountered: [%c]\n", tagType);
+                cerr << "bamtools split ERROR: unknown tag type encountered: " << tagType << endl;
                 return false;
         }
     }
@@ -428,6 +459,16 @@ bool SplitTool::SplitToolPrivate::SplitTagImpl(BamAlignment& al) {
     WriterMap outputFiles;
     WriterMapIterator writerIter;
 
+    // determine tag prefix
+    string tagPrefix = SPLIT_TAG_TOKEN;
+    if ( m_settings->HasCustomTagPrefix )
+        tagPrefix = m_settings->CustomTagPrefix;
+
+    // make sure prefix starts with '.'
+    const size_t dotFound = tagPrefix.find('.');
+    if ( dotFound != 0 )
+        tagPrefix = string(".") + tagPrefix;
+
     // local variables
     const string tag = m_settings->TagToSplit;
     BamWriter* writer;
@@ -438,7 +479,7 @@ bool SplitTool::SplitToolPrivate::SplitTagImpl(BamAlignment& al) {
     if ( al.GetTag(tag, currentValue) ) {
       
         // open new BamWriter, save first alignment
-        outputFilenameStream << m_outputFilenameStub << ".TAG_" << tag << "_" << currentValue << ".bam";
+        outputFilenameStream << m_outputFilenameStub << tagPrefix << tag << "_" << currentValue << ".bam";
         writer = new BamWriter;
         if ( !writer->Open(outputFilenameStream.str(), m_header, m_references) ) {
             cerr << "bamtools split ERROR: could not open " << outputFilenameStream.str()
@@ -467,7 +508,7 @@ bool SplitTool::SplitToolPrivate::SplitTagImpl(BamAlignment& al) {
         if ( writerIter == outputFiles.end() ) {
         
             // open new BamWriter
-            outputFilenameStream << m_outputFilenameStub << ".TAG_" << tag << "_" << currentValue << ".bam";
+            outputFilenameStream << m_outputFilenameStub << tagPrefix << tag << "_" << currentValue << ".bam";
             writer = new BamWriter;
             if ( !writer->Open(outputFilenameStream.str(), m_header, m_references) ) {
                 cerr << "bamtool split ERROR: could not open " << outputFilenameStream.str()
@@ -506,12 +547,20 @@ SplitTool::SplitTool(void)
     , m_impl(0)
 {
     // set program details
-    Options::SetProgramInfo("bamtools split", "splits a BAM file on user-specified property, creating a new BAM output file for each value found", "[-in <filename>] [-stub <filename stub>] < -mapped | -paired | -reference | -tag <TAG> > ");
+    const string name = "bamtools split";
+    const string description = "splits a BAM file on user-specified property, creating a new BAM output file for each value found";
+    const string args = "[-in <filename>] [-stub <filename stub>] < -mapped | -paired | -reference [-refPrefix <prefix>] | -tag <TAG> > ";
+    Options::SetProgramInfo(name, description, args);
     
     // set up options 
     OptionGroup* IO_Opts = Options::CreateOptionGroup("Input & Output");
     Options::AddValueOption("-in",   "BAM filename",  "the input BAM file",  "", m_settings->HasInputFilename,  m_settings->InputFilename,  IO_Opts, Options::StandardIn());
-    Options::AddValueOption("-stub", "filename stub", "prefix stub for output BAM files (default behavior is to use input filename, without .bam extension, as stub). If input is stdin and no stub provided, a timestamp is generated as the stub.", "", m_settings->HasCustomOutputStub, m_settings->CustomOutputStub, IO_Opts);
+    Options::AddValueOption("-refPrefix", "string", "custom prefix for splitting by references. Currently files end with REF_<refName>.bam. This option allows you to replace \"REF_\" with a prefix of your choosing.", "",
+                            m_settings->HasCustomRefPrefix, m_settings->CustomRefPrefix, IO_Opts);
+    Options::AddValueOption("-tagPrefix", "string", "custom prefix for splitting by tags. Current files end with TAG_<tagname>_<tagvalue>.bam. This option allows you to replace \"TAG_\" with a prefix of your choosing.", "",
+                            m_settings->HasCustomTagPrefix, m_settings->CustomTagPrefix, IO_Opts);
+    Options::AddValueOption("-stub", "filename stub", "prefix stub for output BAM files (default behavior is to use input filename, without .bam extension, as stub). If input is stdin and no stub provided, a timestamp is generated as the stub.", "",
+                            m_settings->HasCustomOutputStub, m_settings->CustomOutputStub, IO_Opts);
     
     OptionGroup* SplitOpts = Options::CreateOptionGroup("Split Options");
     Options::AddOption("-mapped",    "split mapped/unmapped alignments",       m_settings->IsSplittingMapped,    SplitOpts);