X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=src%2Ftoolkit%2Fbamtools_split.cpp;h=e6602a9e590e250d3dd204fea990db579db20db4;hb=e7d0ca0a024a13d405872be90f381ff397cdaeec;hp=2560b08cabbe32c61e5e9be45b9b91e71a7aa2e4;hpb=11b57b2ad4d39c9140d35674600dc4a4ff658261;p=bamtools.git diff --git a/src/toolkit/bamtools_split.cpp b/src/toolkit/bamtools_split.cpp index 2560b08..e6602a9 100644 --- a/src/toolkit/bamtools_split.cpp +++ b/src/toolkit/bamtools_split.cpp @@ -1,60 +1,63 @@ // *************************************************************************** // bamtools_split.cpp (c) 2010 Derek Barnett, Erik Garrison // Marth Lab, Department of Biology, Boston College -// All rights reserved. // --------------------------------------------------------------------------- -// Last modified: 19 September 2010 (DB) +// Last modified: 8 December 2011 (DB) // --------------------------------------------------------------------------- -// +// Splits a BAM file on user-specified property, creating a new BAM output +// file for each value found // *************************************************************************** +#include "bamtools_split.h" + +#include +#include +#include +#include +#include +using namespace BamTools; + #include #include #include #include #include #include -#include "bamtools_split.h" -#include "bamtools_options.h" -#include "bamtools_variant.h" -#include "BamReader.h" -#include "BamWriter.h" using namespace std; -using namespace BamTools; namespace BamTools { - // string constants - static const string SPLIT_MAPPED_TOKEN = ".MAPPED"; - 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_"; - - string GetTimestampString(void) { - - // get human readable timestamp - time_t currentTime; - time(¤tTime); - stringstream timeStream(""); - timeStream << ctime(¤tTime); - - // convert whitespace to '_' - string timeString = timeStream.str(); - size_t found = timeString.find(" "); - while (found != string::npos) { - timeString.replace(found, 1, "_"); - found = timeString.find(" ", found+1); - } - return timeString; - } - - // remove copy of filename without extension - // (so /path/to/file.txt becomes /path/to/file ) - string RemoveFilenameExtension(const string& filename) { - size_t found = filename.rfind("."); - return filename.substr(0, found); +// string constants +static const string SPLIT_MAPPED_TOKEN = ".MAPPED"; +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_"; + +string GetTimestampString(void) { + + // get human readable timestamp + time_t currentTime; + time(¤tTime); + stringstream timeStream(""); + timeStream << ctime(¤tTime); + + // convert whitespace to '_' + string timeString = timeStream.str(); + size_t found = timeString.find(" "); + while (found != string::npos) { + timeString.replace(found, 1, "_"); + found = timeString.find(" ", found+1); } + return timeString; +} + +// remove copy of filename without extension +// (so /path/to/file.txt becomes /path/to/file ) +string RemoveFilenameExtension(const string& filename) { + size_t found = filename.rfind("."); + return filename.substr(0, found); +} } // namespace BamTools @@ -66,6 +69,7 @@ struct SplitTool::SplitSettings { // flags bool HasInputFilename; bool HasCustomOutputStub; + bool HasCustomRefPrefix; bool IsSplittingMapped; bool IsSplittingPaired; bool IsSplittingReference; @@ -73,6 +77,7 @@ struct SplitTool::SplitSettings { // string args string CustomOutputStub; + string CustomRefPrefix; string InputFilename; string TagToSplit; @@ -80,11 +85,13 @@ struct SplitTool::SplitSettings { SplitSettings(void) : HasInputFilename(false) , HasCustomOutputStub(false) + , HasCustomRefPrefix(false) , IsSplittingMapped(false) , IsSplittingPaired(false) , IsSplittingReference(false) , IsSplittingTag(false) , CustomOutputStub("") + , CustomRefPrefix("") , InputFilename(Options::StandardIn()) , TagToSplit("") { } @@ -97,8 +104,13 @@ class SplitTool::SplitToolPrivate { // ctor & dtor public: - SplitToolPrivate(SplitTool::SplitSettings* settings); - ~SplitToolPrivate(void); + SplitToolPrivate(SplitTool::SplitSettings* settings) + : m_settings(settings) + { } + + ~SplitToolPrivate(void) { + m_reader.Close(); + } // 'public' interface public: @@ -106,16 +118,26 @@ class SplitTool::SplitToolPrivate { // internal methods private: + // close & delete BamWriters in map + template + void CloseWriters(map& writers); + // calculate output stub based on IO args given void DetermineOutputFilenameStub(void); + // open our BamReader bool OpenReader(void); + // split alignments in BAM file based on isMapped property bool SplitMapped(void); + // split alignments in BAM file based on isPaired property bool SplitPaired(void); + // split alignments in BAM file based on refID property bool SplitReference(void); + // finds first alignment and calls corresponding SplitTagImpl<> + // depending on tag type bool SplitTag(void); - bool SplitTag_Int(BamAlignment& al); - bool SplitTag_UInt(BamAlignment& al); - bool SplitTag_Real(BamAlignment& al); - bool SplitTag_String(BamAlignment& al); + // templated split tag implementation + // handle the various types that are possible for tags + template + bool SplitTagImpl(BamAlignment& al); // data members private: @@ -126,16 +148,6 @@ class SplitTool::SplitToolPrivate { RefVector m_references; }; -// constructor -SplitTool::SplitToolPrivate::SplitToolPrivate(SplitTool::SplitSettings* settings) - : m_settings(settings) -{ } - -// destructor -SplitTool::SplitToolPrivate::~SplitToolPrivate(void) { - m_reader.Close(); -} - void SplitTool::SplitToolPrivate::DetermineOutputFilenameStub(void) { // if user supplied output filename stub, use that @@ -152,10 +164,14 @@ void SplitTool::SplitToolPrivate::DetermineOutputFilenameStub(void) { } bool SplitTool::SplitToolPrivate::OpenReader(void) { + + // attempt to open BAM file if ( !m_reader.Open(m_settings->InputFilename) ) { - cerr << "ERROR: SplitTool could not open BAM file: " << m_settings->InputFilename << endl; + cerr << "bamtools split ERROR: could not open BAM file: " << m_settings->InputFilename << endl; return false; } + + // save file 'metadata' & return success m_header = m_reader.GetHeaderText(); m_references = m_reader.GetReferenceData(); return true; @@ -167,7 +183,8 @@ bool SplitTool::SplitToolPrivate::Run(void) { DetermineOutputFilenameStub(); // open up BamReader - if ( !OpenReader() ) return false; + if ( !OpenReader() ) + return false; // determine split type from settings if ( m_settings->IsSplittingMapped ) return SplitMapped(); @@ -176,7 +193,8 @@ bool SplitTool::SplitToolPrivate::Run(void) { if ( m_settings->IsSplittingTag ) return SplitTag(); // if we get here, no property was specified - cerr << "No property given to split on... Please use -mapped, -paired, -reference, or -tag TAG to specifiy split behavior." << endl; + cerr << "bamtools split ERROR: no property given to split on... " << endl + << "Please use -mapped, -paired, -reference, or -tag TAG to specifiy desired split behavior." << endl; return false; } @@ -200,9 +218,15 @@ bool SplitTool::SplitToolPrivate::SplitMapped(void) { if ( writerIter == outputFiles.end() ) { // open new BamWriter + const string outputFilename = m_outputFilenameStub + ( isCurrentAlignmentMapped + ? SPLIT_MAPPED_TOKEN + : SPLIT_UNMAPPED_TOKEN ) + ".bam"; writer = new BamWriter; - const string outputFilename = m_outputFilenameStub + ( isCurrentAlignmentMapped ? SPLIT_MAPPED_TOKEN : SPLIT_UNMAPPED_TOKEN ) + ".bam"; - writer->Open(outputFilename, m_header, m_references); + if ( !writer->Open(outputFilename, m_header, m_references) ) { + cerr << "bamtools split ERROR: could not open " << outputFilename + << " for writing." << endl; + return false; + } // store in map outputFiles.insert( make_pair(isCurrentAlignmentMapped, writer) ); @@ -212,19 +236,12 @@ bool SplitTool::SplitToolPrivate::SplitMapped(void) { else writer = (*writerIter).second; // store alignment in proper BAM output file - if ( writer ) + if ( writer ) writer->SaveAlignment(al); } // clean up BamWriters - map::iterator writerEnd = outputFiles.end(); - for ( writerIter = outputFiles.begin() ; writerIter != writerEnd; ++writerIter ) { - BamWriter* writer = (*writerIter).second; - if ( writer == 0 ) continue; - writer->Close(); - delete writer; - writer = 0; - } + CloseWriters(outputFiles); // return success return true; @@ -250,9 +267,15 @@ bool SplitTool::SplitToolPrivate::SplitPaired(void) { if ( writerIter == outputFiles.end() ) { // open new BamWriter + const string outputFilename = m_outputFilenameStub + ( isCurrentAlignmentPaired + ? SPLIT_PAIRED_TOKEN + : SPLIT_SINGLE_TOKEN ) + ".bam"; writer = new BamWriter; - const string outputFilename = m_outputFilenameStub + ( isCurrentAlignmentPaired ? SPLIT_PAIRED_TOKEN : SPLIT_SINGLE_TOKEN ) + ".bam"; - writer->Open(outputFilename, m_header, m_references); + if ( !writer->Open(outputFilename, m_header, m_references) ) { + cerr << "bamtool split ERROR: could not open " << outputFilename + << " for writing." << endl; + return false; + } // store in map outputFiles.insert( make_pair(isCurrentAlignmentPaired, writer) ); @@ -267,14 +290,7 @@ bool SplitTool::SplitToolPrivate::SplitPaired(void) { } // clean up BamWriters - map::iterator writerEnd = outputFiles.end(); - for ( writerIter = outputFiles.begin() ; writerIter != writerEnd; ++writerIter ) { - BamWriter* writer = (*writerIter).second; - if (writer == 0 ) continue; - writer->Close(); - delete writer; - writer = 0; - } + CloseWriters(outputFiles); // return success return true; @@ -286,6 +302,16 @@ bool SplitTool::SplitToolPrivate::SplitReference(void) { map outputFiles; map::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; @@ -299,12 +325,24 @@ 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 writer = new BamWriter; - const string refName = m_references.at(currentRefId).RefName; - const string outputFilename = m_outputFilenameStub + SPLIT_REFERENCE_TOKEN + refName + ".bam"; - writer->Open(outputFilename, m_header, m_references); - + if ( !writer->Open(outputFilename, m_header, m_references) ) { + cerr << "bamtools split ERROR: could not open " << outputFilename + << " for writing." << endl; + return false; + } + // store in map outputFiles.insert( make_pair(currentRefId, writer) ); } @@ -318,19 +356,13 @@ bool SplitTool::SplitToolPrivate::SplitReference(void) { } // clean up BamWriters - map::iterator writerEnd = outputFiles.end(); - for ( writerIter = outputFiles.begin(); writerIter != writerEnd; ++writerIter ) { - BamWriter* writer = (*writerIter).second; - if (writer == 0 ) continue; - writer->Close(); - delete writer; - writer = 0; - } + CloseWriters(outputFiles); // return success return true; } +// finds first alignment and calls corresponding SplitTagImpl<>() depending on tag type bool SplitTool::SplitToolPrivate::SplitTag(void) { // iterate through alignments, until we hit TAG @@ -339,32 +371,37 @@ bool SplitTool::SplitToolPrivate::SplitTag(void) { // look for tag in this alignment and get tag type char tagType(0); - if ( !al.GetTagType(m_settings->TagToSplit, tagType) ) continue; + if ( !al.GetTagType(m_settings->TagToSplit, tagType) ) + continue; // request split method based on tag type // pass it the current alignment found - switch (tagType) { + switch ( tagType ) { - case 'c' : - case 's' : - case 'i' : - return SplitTag_Int(al); + case (Constants::BAM_TAG_TYPE_INT8) : + case (Constants::BAM_TAG_TYPE_INT16) : + case (Constants::BAM_TAG_TYPE_INT32) : + return SplitTagImpl(al); - case 'C' : - case 'S' : - case 'I' : - return SplitTag_UInt(al); + case (Constants::BAM_TAG_TYPE_UINT8) : + case (Constants::BAM_TAG_TYPE_UINT16) : + case (Constants::BAM_TAG_TYPE_UINT32) : + return SplitTagImpl(al); - case 'f' : - return SplitTag_Real(al); + case (Constants::BAM_TAG_TYPE_FLOAT) : + return SplitTagImpl(al); - case 'A': - case 'Z': - case 'H': - return SplitTag_String(al); + case (Constants::BAM_TAG_TYPE_ASCII) : + case (Constants::BAM_TAG_TYPE_STRING) : + case (Constants::BAM_TAG_TYPE_HEX) : + return SplitTagImpl(al); + + case (Constants::BAM_TAG_TYPE_ARRAY) : + cerr << "bamtools split ERROR: array tag types are not supported" << endl; + return false; default: - fprintf(stderr, "ERROR: Unknown tag storage class encountered: [%c]\n", tagType); + cerr << "bamtools split ERROR: unknown tag type encountered: " << tagType << endl; return false; } } @@ -373,175 +410,67 @@ bool SplitTool::SplitToolPrivate::SplitTag(void) { return true; } -bool SplitTool::SplitToolPrivate::SplitTag_Int(BamAlignment& al) { - - // set up splitting data structure - map outputFiles; - map::iterator writerIter; +// -------------------------------------------------------------------------------- +// template method implementation +// *Technical Note* - use of template methods declared & defined in ".cpp" file +// goes against normal practices, but works here because these +// are purely internal (no one can call from outside this file) - // local variables - const string tag = m_settings->TagToSplit; - BamWriter* writer; - stringstream outputFilenameStream(""); - int32_t currentValue; - - // retrieve first alignment tag value - if ( al.GetTag(tag, currentValue) ) { - - // open new BamWriter, save first alignment - writer = new BamWriter; - outputFilenameStream << m_outputFilenameStub << ".TAG_" << tag << "_" << currentValue << ".bam"; - writer->Open(outputFilenameStream.str(), m_header, m_references); - writer->SaveAlignment(al); - - // store in map - outputFiles.insert( make_pair(currentValue, writer) ); - - // reset stream - outputFilenameStream.str(""); - } - - // iterate through remaining alignments - while ( m_reader.GetNextAlignment(al) ) { - - // skip if this alignment doesn't have TAG - if ( !al.GetTag(tag, currentValue) ) continue; - - // look up tag value in map - writerIter = outputFiles.find(currentValue); - - // if no writer associated with this value - if ( writerIter == outputFiles.end() ) { - - // open new BamWriter - writer = new BamWriter; - outputFilenameStream << m_outputFilenameStub << ".TAG_" << tag << "_" << currentValue << ".bam"; - writer->Open(outputFilenameStream.str(), m_header, m_references); - - // store in map - outputFiles.insert( make_pair(currentValue, writer) ); - - // reset stream - outputFilenameStream.str(""); - } - - // else grab corresponding writer - else writer = (*writerIter).second; - - // store alignment in proper BAM output file - if ( writer ) - writer->SaveAlignment(al); - } - - // clean up BamWriters - map::iterator writerEnd = outputFiles.end(); - for ( writerIter = outputFiles.begin(); writerIter != writerEnd; ++writerIter ) { +// close BamWriters & delete pointers +template +void SplitTool::SplitToolPrivate::CloseWriters(map& writers) { + + typedef map WriterMap; + typedef typename WriterMap::iterator WriterMapIterator; + + // iterate over writers + WriterMapIterator writerIter = writers.begin(); + WriterMapIterator writerEnd = writers.end(); + for ( ; writerIter != writerEnd; ++writerIter ) { BamWriter* writer = (*writerIter).second; - if (writer == 0 ) continue; + if ( writer == 0 ) continue; + + // close BamWriter writer->Close(); + + // destroy BamWriter delete writer; writer = 0; } - - // return success - return true; + + // clear the container (destroying the items doesn't remove them) + writers.clear(); } -bool SplitTool::SplitToolPrivate::SplitTag_UInt(BamAlignment& al) { +// handle the various types that are possible for tags +template +bool SplitTool::SplitToolPrivate::SplitTagImpl(BamAlignment& al) { + + typedef T TagValueType; + typedef map WriterMap; + typedef typename WriterMap::iterator WriterMapIterator; // set up splitting data structure - map outputFiles; - map::iterator writerIter; + WriterMap outputFiles; + WriterMapIterator writerIter; // local variables const string tag = m_settings->TagToSplit; BamWriter* writer; stringstream outputFilenameStream(""); - uint32_t currentValue; - - int alignmentsIgnored = 0; + TagValueType currentValue; // retrieve first alignment tag value if ( al.GetTag(tag, currentValue) ) { // open new BamWriter, save first alignment - writer = new BamWriter; outputFilenameStream << m_outputFilenameStub << ".TAG_" << tag << "_" << currentValue << ".bam"; - writer->Open(outputFilenameStream.str(), m_header, m_references); - writer->SaveAlignment(al); - - // store in map - outputFiles.insert( make_pair(currentValue, writer) ); - - // reset stream - outputFilenameStream.str(""); - } else ++alignmentsIgnored; - - // iterate through remaining alignments - while ( m_reader.GetNextAlignment(al) ) { - - // skip if this alignment doesn't have TAG - if ( !al.GetTag(tag, currentValue) ) { ++alignmentsIgnored; continue; } - - // look up tag value in map - writerIter = outputFiles.find(currentValue); - - // if no writer associated with this value - if ( writerIter == outputFiles.end() ) { - - // open new BamWriter - writer = new BamWriter; - outputFilenameStream << m_outputFilenameStub << ".TAG_" << tag << "_" << currentValue << ".bam"; - writer->Open(outputFilenameStream.str(), m_header, m_references); - - // store in map - outputFiles.insert( make_pair(currentValue, writer) ); - - // reset stream - outputFilenameStream.str(""); - } - - // else grab corresponding writer - else writer = (*writerIter).second; - - // store alignment in proper BAM output file - if ( writer ) - writer->SaveAlignment(al); - } - - // clean up BamWriters - map::iterator writerEnd = outputFiles.end(); - for ( writerIter = outputFiles.begin(); writerIter != writerEnd; ++writerIter ) { - BamWriter* writer = (*writerIter).second; - if (writer == 0 ) continue; - writer->Close(); - delete writer; - writer = 0; - } - - // return success - return true; -} - -bool SplitTool::SplitToolPrivate::SplitTag_Real(BamAlignment& al) { - - // set up splitting data structure - map outputFiles; - map::iterator writerIter; - - // local variables - const string tag = m_settings->TagToSplit; - BamWriter* writer; - stringstream outputFilenameStream(""); - float currentValue; - - // retrieve first alignment tag value - if ( al.GetTag(tag, currentValue) ) { - - // open new BamWriter, save first alignment writer = new BamWriter; - outputFilenameStream << m_outputFilenameStub << ".TAG_" << tag << "_" << currentValue << ".bam"; - writer->Open(outputFilenameStream.str(), m_header, m_references); + if ( !writer->Open(outputFilenameStream.str(), m_header, m_references) ) { + cerr << "bamtools split ERROR: could not open " << outputFilenameStream.str() + << " for writing." << endl; + return false; + } writer->SaveAlignment(al); // store in map @@ -564,84 +493,14 @@ bool SplitTool::SplitToolPrivate::SplitTag_Real(BamAlignment& al) { if ( writerIter == outputFiles.end() ) { // open new BamWriter - writer = new BamWriter; outputFilenameStream << m_outputFilenameStub << ".TAG_" << tag << "_" << currentValue << ".bam"; - writer->Open(outputFilenameStream.str(), m_header, m_references); - - // store in map - outputFiles.insert( make_pair(currentValue, writer) ); - - // reset stream - outputFilenameStream.str(""); - } - - // else grab corresponding writer - else writer = (*writerIter).second; - - // store alignment in proper BAM output file - if ( writer ) - writer->SaveAlignment(al); - } - - // clean up BamWriters - map::iterator writerEnd = outputFiles.end(); - for ( writerIter = outputFiles.begin(); writerIter != writerEnd; ++writerIter ) { - BamWriter* writer = (*writerIter).second; - if (writer == 0 ) continue; - writer->Close(); - delete writer; - writer = 0; - } - - // return success - return true; -} - -bool SplitTool::SplitToolPrivate::SplitTag_String(BamAlignment& al) { - - // set up splitting data structure - map outputFiles; - map::iterator writerIter; - - // local variables - const string tag = m_settings->TagToSplit; - BamWriter* writer; - stringstream outputFilenameStream(""); - string currentValue; - - // retrieve first alignment tag value - if ( al.GetTag(tag, currentValue) ) { - - // open new BamWriter, save first alignment - writer = new BamWriter; - outputFilenameStream << m_outputFilenameStub << ".TAG_" << tag << "_" << currentValue << ".bam"; - writer->Open(outputFilenameStream.str(), m_header, m_references); - writer->SaveAlignment(al); - - // store in map - outputFiles.insert( make_pair(currentValue, writer) ); - - // reset stream - outputFilenameStream.str(""); - } - - // iterate through remaining alignments - while ( m_reader.GetNextAlignment(al) ) { - - // skip if this alignment doesn't have TAG - if ( !al.GetTag(tag, currentValue) ) continue; - - // look up tag value in map - writerIter = outputFiles.find(currentValue); - - // if no writer associated with this value - if ( writerIter == outputFiles.end() ) { - - // open new BamWriter writer = new BamWriter; - outputFilenameStream << m_outputFilenameStub << ".TAG_" << tag << "_" << currentValue << ".bam"; - writer->Open(outputFilenameStream.str(), m_header, m_references); - + if ( !writer->Open(outputFilenameStream.str(), m_header, m_references) ) { + cerr << "bamtool split ERROR: could not open " << outputFilenameStream.str() + << " for writing." << endl; + return false; + } + // store in map outputFiles.insert( make_pair(currentValue, writer) ); @@ -657,18 +516,11 @@ bool SplitTool::SplitToolPrivate::SplitTag_String(BamAlignment& al) { writer->SaveAlignment(al); } - // clean up BamWriters - map::iterator writerEnd = outputFiles.end(); - for ( writerIter = outputFiles.begin(); writerIter != writerEnd; ++writerIter ) { - BamWriter* writer = (*writerIter).second; - if (writer == 0 ) continue; - writer->Close(); - delete writer; - writer = 0; - } + // clean up BamWriters + CloseWriters(outputFiles); // return success - return true; + return true; } // --------------------------------------------- @@ -680,12 +532,18 @@ 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 ] [-stub ] < -mapped | -paired | -reference | -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 ] [-stub ] < -mapped | -paired | -reference [-refPrefix ] | -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("-in", "BAM filename", "the input BAM file", "", m_settings->HasInputFilename, m_settings->InputFilename, IO_Opts, Options::StandardIn()); + Options::AddValueOption("-refPrefix", "string", "custom prefix for splitting by references. Currently files end with REF_.bam. This option allows you to replace \"REF_\" with a prefix of your choosing.", "", + m_settings->HasCustomRefPrefix, m_settings->CustomRefPrefix, 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); @@ -714,10 +572,10 @@ int SplitTool::Run(int argc, char* argv[]) { // parse command line arguments Options::Parse(argc, argv, 1); - // initialize internal implementation + // initialize SplitTool with settings m_impl = new SplitToolPrivate(m_settings); - // run tool, return success/fail + // run SplitTool, return success/fail if ( m_impl->Run() ) return 0; else