/** ** Copyright (c) 2007-2009 Illumina, Inc. ** ** This software is covered by the "Illumina Genome Analyzer Software ** License Agreement" and the "Illumina Source Code License Agreement", ** and certain third party copyright/licenses, and any user of this ** source file is bound by the terms therein (see accompanying files ** Illumina_Genome_Analyzer_Software_License_Agreement.pdf and ** Illumina_Source_Code_License_Agreement.pdf and third party ** copyright/license notices). ** ** This file is part of the Consensus Assessment of Sequence And VAriation ** (CASAVA) software package. ** ** \file BclDemultiplexer.cpp ** ** \brief Top level library component to demultiplex a tile stack of bcl files. ** ** \author Roman Petrovski **/ #include #include #include #include #include #include "common/Exceptions.hh" #include "alignment/BclReader.hh" #include "demultiplex/BarcodeTranslationTable.hh" namespace casava { namespace demultiplex { static std::ostream & operator <<(std::ostream &os, const SamplePath &path) { return os << path.string(); } std::ostream & printStdPair(std::ostream &os, const BarcodeTranslationTable::BarcodeDirPair &kv) { return os << kv.first << "->" << *kv.second << "\n"; } std::ostream & operator <<(std::ostream &os, const BarcodeTranslationTable &btt) { os << "Output Paths:\n"; std::copy(btt.begin(), btt.end(), std::ostream_iterator(os, "\n")); os << "Barcode Paths:\n"; std::for_each(btt.correctedBarcodeOutDir_.begin(), btt.correctedBarcodeOutDir_.end(), boost::bind(&printStdPair, boost::ref(os), _1)); return os; } std::string BarcodeTranslationTable::removeComponentSeparator(const std::string &barcode) { std::string ret; std::remove_copy_if(barcode.begin(), barcode.end(), std::back_inserter(ret), boost::bind(&boost::cref, _1) == barcodeComponentSeparator_); return ret; } void BarcodeTranslationTable::insertBarcode(const std::string &barcode, const unsigned currentComponentIndex, std::string::size_type pos, const unsigned int allowedMismatchesLeft, const_iterator outDirPathIterator, BarcodeOutDirMap &container) const { if (allowedMismatchesLeft) { // insert the original insertBarcode(barcode, currentComponentIndex, pos, allowedMismatchesLeft -1, outDirPathIterator, container); // simulate the mismatching ones static const struct ErrorsLookup: public std::vector { ErrorsLookup() : std::vector('T' + 1) { at('A') = "CGTN"; at('C') = "GTNA"; at('G') = "TNAC"; at('T') = "NACG"; at('N') = "ACGT"; } } mismatchesLookup; while(pos-- && barcodeComponentSeparator_ != barcode[pos]) { const std::string &mismatches(mismatchesLookup[barcode[pos]]); std::cerr << "Generating Mismatches for pos: " << pos << " mismatches:" << mismatches << "\n"; BOOST_FOREACH(const char base, mismatches) { std::string correctedBarcode(barcode); correctedBarcode[pos] = base; insertBarcode(correctedBarcode, currentComponentIndex, pos, allowedMismatchesLeft -1, outDirPathIterator, container); } } } else if (currentComponentIndex) { // simulate mismatches in the next barcode component //std::cerr << "component before: " << currentComponentIndex << " start pos: " << pos << " barcode: " << barcode << "\n"; const std::string::size_type nextComponentStartPos = barcode.rfind(barcodeComponentSeparator_, pos - 1); BOOST_ASSERT(std::string::npos != nextComponentStartPos && "Mismatch between delimited barcode components and the component mismatch configuration"); //std::cerr << "component: " << currentComponentIndex << " start pos: " << nextComponentStartPos << "\n"; insertBarcode(barcode, currentComponentIndex - 1, nextComponentStartPos, componentMaxMismatches_.at(currentComponentIndex - 1), outDirPathIterator, container); } else { // the actual insertion BarcodeOutDirMap::value_type insertKv(removeComponentSeparator(barcode), outDirPathIterator); std::pair p = container.insert(insertKv); const std::string &outDirPath(outDirPathIterator->string()); if (!p.second) { const std::string &existingOutDirPath(p.first->second->string()); if(p.first->second != outDirPathIterator) { BOOST_THROW_EXCEPTION(cc::InvalidParameterException( (boost::format("Barcode collision. Barcode: %s OutputDir: %s, ConflictingDir: %s") % barcode % outDirPath % existingOutDirPath).str())); } std::cerr << "BarcodeTranslationTable::insertBarcode existing:" << barcode << ' ' << outDirPath << '\n'; } else { std::cerr << "BarcodeTranslationTable::insertBarcode:" << barcode << ' ' << outDirPath << '\n'; } } } } // namespace demultiplex } // namespace casava