[med-svn] [salmon] 04/11: new upstream version

Sascha Steinbiss satta at debian.org
Sat Sep 10 13:22:41 UTC 2016


This is an automated email from the git hooks/post-receive script.

satta pushed a commit to branch master
in repository salmon.

commit 9af2d25935eb180394be8d7fd592d41b2da2f657
Author: Sascha Steinbiss <satta at debian.org>
Date:   Sat Sep 10 12:53:17 2016 +0000

    new upstream version
---
 debian/changelog                                |   2 +
 debian/patches/fix-unittest.patch               |   2 +-
 debian/patches/use_debian_packaged_rapmap.patch |   5 +-
 debian/rapmap/BooPHF.hpp                        |  24 +-
 debian/rapmap/PairAlignmentFormatter.hpp        |  29 ++
 debian/rapmap/RapMapSAIndex.hpp                 |   4 +-
 debian/rapmap/RapMapSAIndexer.cpp               |  66 +--
 debian/rapmap/RapMapUtils.cpp                   | 584 ++++++++++++++++++++++++
 debian/rapmap/RapMapUtils.hpp                   |  33 +-
 debian/rapmap/SingleAlignmentFormatter.hpp      |  22 +
 debian/rules                                    |  16 +-
 11 files changed, 722 insertions(+), 65 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 3f7e795..b2cd9bf 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -7,6 +7,8 @@ salmon (0.7.2+ds1-1) unstable; urgency=medium
   * d/watch: use xz compression
   * Include necessary parts of RapMap code until upstream sorts out
     code embedding.
+  * Adapt spdlog API use to match version of spdlog packaged in Debian.
+    Closes: #835720
 
  -- Andreas Tille <tille at debian.org>  Tue, 30 Aug 2016 09:10:48 +0200
 
diff --git a/debian/patches/fix-unittest.patch b/debian/patches/fix-unittest.patch
index 2be00d5..6c0b34c 100644
--- a/debian/patches/fix-unittest.patch
+++ b/debian/patches/fix-unittest.patch
@@ -1,6 +1,6 @@
 --- a/src/CMakeLists.txt
 +++ b/src/CMakeLists.txt
-@@ -236,7 +236,7 @@
+@@ -237,7 +237,7 @@
  )
  
  include(InstallRequiredSystemLibraries)
diff --git a/debian/patches/use_debian_packaged_rapmap.patch b/debian/patches/use_debian_packaged_rapmap.patch
index ffc288c..25b3eac 100644
--- a/debian/patches/use_debian_packaged_rapmap.patch
+++ b/debian/patches/use_debian_packaged_rapmap.patch
@@ -31,7 +31,7 @@
  )
  
  set (SALMON_ALIGN_SRCS
-@@ -64,6 +54,15 @@
+@@ -64,6 +54,16 @@
  SGSmooth.cpp
  )
  
@@ -41,13 +41,14 @@
 +RapMapFileSystem.cpp
 +RapMapSAIndex.cpp
 +RapMapSAIndexer.cpp
++RapMapUtils.cpp
 +rank9b.cpp
 +)
 +
  set ( UNIT_TESTS_SRCS
      ${GAT_SOURCE_DIR}/tests/UnitTests.cpp
      FragmentLengthDistribution.cpp
-@@ -104,9 +103,9 @@
+@@ -104,9 +104,9 @@
  endif()
  
  # Build the salmon executable
diff --git a/debian/rapmap/BooPHF.hpp b/debian/rapmap/BooPHF.hpp
index 64b11c7..23c3699 100644
--- a/debian/rapmap/BooPHF.hpp
+++ b/debian/rapmap/BooPHF.hpp
@@ -533,7 +533,7 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 		//for debug purposes
 		void print() const
 		{
-			printf("bit array of size %llu: \n", _size);
+			printf("bit array of size %lli: \n",_size);
 			for(uint64_t ii = 0; ii< _size; ii++)
 			{
 				if(ii%10==0)
@@ -546,7 +546,7 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 			printf("rank array : size %lu \n",_ranks.size());
 			for (uint64_t ii = 0; ii< _ranks.size(); ii++)
 			{
-				printf("%llu:  %llu,  ",ii,_ranks[ii]);
+				printf("%llu :  %lli,  ",ii,_ranks[ii]);
 			}
 			printf("\n");
 		}
@@ -736,6 +736,8 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 		{
 			if(n ==0) return;
 			
+			_fastmode = false;
+			
 			if(_percent_elem_loaded_for_fastMode > 0.0 )
 				_fastmode =true;
 
@@ -748,7 +750,7 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 			if(_fastmode)
 				_progressBar.init( _nelem * (_fastModeLevel+1) +  ( _nelem * pow(_proba_collision,_fastModeLevel)) * (_nb_levels-(_fastModeLevel+1))    ,"Building BooPHF",num_thread);
 			else
-				_progressBar.init( _nelem * _nb_levels ,"Building BooPHF");
+				_progressBar.init( _nelem * _nb_levels ,"Building BooPHF",num_thread);
 			}
 
 			uint64_t offset = 0;
@@ -851,7 +853,6 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 			auto until = *until_p;
 			uint64_t inbuff =0;
 
-
 			
 			for (bool isRunning=true;  isRunning ; )
 			{
@@ -879,8 +880,9 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 					{
 							__sync_fetch_and_add(& _cptLevel,1);
 
-						if(i == _fastModeLevel && _fastmode)
+						if(_fastmode && i == _fastModeLevel)
 						{
+
 							uint64_t idxl2 = __sync_fetch_and_add(& _idxLevelsetLevelFastmode,1);
 							//si depasse taille attendue pour setLevelFastmode, fall back sur slow mode mais devrait pas arriver si hash ok et proba avec nous
 							if(idxl2>= setLevelFastmode.size())
@@ -892,6 +894,7 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 						//insert to level i+1 : either next level of the cascade or final hash if last level reached
 						if(i == _nb_levels-1) //stop cascade here, insert into exact hash
 						{
+
 							uint64_t hashidx =  __sync_fetch_and_add (& _hashidx, 1);
 
 							pthread_mutex_lock(&_mutex); //see later if possible to avoid this, mais pas bcp item vont la
@@ -901,6 +904,7 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 						}
 						else
 						{
+
 							//computes next hash
 
 							if ( level == 0)
@@ -1047,12 +1051,10 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 				 if(pow(_proba_collision,ii) < _percent_elem_loaded_for_fastMode)
 				 {
 				 	_fastModeLevel = ii;
-				 	// printf("fast mode level :  %i \n",ii);
+				 	 //printf("fast mode level :  %i \n",ii);
 				 	break;
 				 }
 			}
-
-
 		}
 
 
@@ -1123,7 +1125,7 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 			t_arg.until_p =  std::static_pointer_cast<void>(std::make_shared<it_type>(input_range.end()));
 
 			t_arg.level = i;
-			if(i >= (_fastModeLevel+1) && _fastmode)
+			if(_fastmode && i >= (_fastModeLevel+1))
 			{
 				auto data_iterator = boomphf::range(static_cast<const elem_t*>( &setLevelFastmode[0]), static_cast<const elem_t*>( (&setLevelFastmode[0]) +setLevelFastmode.size()));
                 typedef decltype(data_iterator.begin()) fastmode_it_type;
@@ -1146,9 +1148,9 @@ we need this 2-functors scheme because HashFunctors won't work with unordered_ma
 			{
 				pthread_join(tab_threads[ii], NULL);
 			}
-		//	printf("\ngoing to level %i  : %llu elems  %.2f %%  expected : %.2f %% \n",i,_cptLevel,100.0* _cptLevel/(float)_nelem,100.0* pow(_proba_collision,i) );
+			//printf("\ngoing to level %i  : %llu elems  %.2f %%  expected : %.2f %% \n",i,_cptLevel,100.0* _cptLevel/(float)_nelem,100.0* pow(_proba_collision,i) );
 
-			if(i == _fastModeLevel) //shrink to actual number of elements in set
+			if(_fastmode && i == _fastModeLevel) //shrink to actual number of elements in set
 			{
 				//printf("resize setLevelFastmode to %lli \n",_idxLevelsetLevelFastmode);
 				setLevelFastmode.resize(_idxLevelsetLevelFastmode);
diff --git a/debian/rapmap/PairAlignmentFormatter.hpp b/debian/rapmap/PairAlignmentFormatter.hpp
new file mode 100644
index 0000000..a3e90fe
--- /dev/null
+++ b/debian/rapmap/PairAlignmentFormatter.hpp
@@ -0,0 +1,29 @@
+#ifndef __PAIR_ALIGNMENT_FORMATTER_HPP__
+#define __PAIR_ALIGNMENT_FORMATTER_HPP__
+
+#include "RapMapUtils.hpp"
+
+template <typename IndexPtrT>
+struct PairAlignmentFormatter {
+    PairAlignmentFormatter(IndexPtrT indexIn) : index(indexIn),
+    read1Temp(1000, 'A'),
+    qual1Temp(1000, '~'),
+    read2Temp(1000, 'A'),
+    qual2Temp(1000, '~'),
+    cigarStr1(buff1, 1000),
+    cigarStr2(buff2, 1000) {
+    }
+
+    // Data members
+    IndexPtrT index;
+    std::string read1Temp;
+    std::string qual1Temp;
+    std::string read2Temp;
+    std::string qual2Temp;
+    char buff1[1000];
+    char buff2[1000];
+    rapmap::utils::FixedWriter cigarStr1;
+    rapmap::utils::FixedWriter cigarStr2;
+};
+
+#endif //__PAIR_ALIGNMENT_FORMATTER_HPP__
diff --git a/debian/rapmap/RapMapSAIndex.hpp b/debian/rapmap/RapMapSAIndex.hpp
index 075846e..3e84631 100644
--- a/debian/rapmap/RapMapSAIndex.hpp
+++ b/debian/rapmap/RapMapSAIndex.hpp
@@ -7,7 +7,9 @@
 #include <cereal/archives/binary.hpp>
 
 #include "spdlog/spdlog.h"
-#include "spdlog/fmt/bundled/format.h"
+#include "spdlog/fmt/ostr.h"
+#include "spdlog/fmt/fmt.h"
+
 
 #include "google/dense_hash_map"
 #include "bit_array.h"
diff --git a/debian/rapmap/RapMapSAIndexer.cpp b/debian/rapmap/RapMapSAIndexer.cpp
index 83a1491..473c6a7 100644
--- a/debian/rapmap/RapMapSAIndexer.cpp
+++ b/debian/rapmap/RapMapSAIndexer.cpp
@@ -25,10 +25,9 @@
 
 #include "spdlog/spdlog.h"
 
+#include "FastxParser.hpp"
 // Jellyfish 2 include
 #include "jellyfish/mer_dna.hpp"
-#include "jellyfish/stream_manager.hpp"
-#include "jellyfish/whole_sequence_parser.hpp"
 
 #include "divsufsort.h"
 #include "divsufsort64.h"
@@ -53,9 +52,7 @@
 
 #include <chrono>
 
-using stream_manager =
-    jellyfish::stream_manager<std::vector<std::string>::const_iterator>;
-using single_parser = jellyfish::whole_sequence_parser<stream_manager>;
+using single_parser = fastx_parser::FastxParser<fastx_parser::ReadSeq>;
 using TranscriptID = uint32_t;
 using TranscriptIDVector = std::vector<TranscriptID>;
 using KmerIDMap = std::vector<TranscriptIDVector>;
@@ -392,7 +389,9 @@ bool buildHash(const std::string& outputDir, std::string& concatText,
 template <typename ParserT> //, typename CoverageCalculator>
 void indexTranscriptsSA(ParserT* parser, std::string& outputDir,
                         bool noClipPolyA, bool usePerfectHash,
-                        uint32_t numHashThreads, std::mutex& iomutex,
+                        uint32_t numHashThreads, 
+                        std::string& sepStr,
+                        std::mutex& iomutex,
                         std::shared_ptr<spdlog::logger> log) {
   // Seed with a real random value, if available
   std::random_device rd;
@@ -435,12 +434,13 @@ void indexTranscriptsSA(ParserT* parser, std::string& outputDir,
   fmt::MemoryWriter txpSeqStream;
   {
     ScopedTimer timer;
-    while (true) {
-      typename ParserT::job j(*parser);
-      if (j.is_empty())
-        break;
-      for (size_t i = 0; i < j->nb_filled; ++i) { // For each sequence
-        std::string& readStr = j->data[i].seq;
+    // Get the read group by which this thread will
+    // communicate with the parser (*once per-thread*)
+    auto rg = parser->getReadGroup();
+
+    while (parser->refill(rg)) {
+      for (auto& read : rg) { // for each sequence
+        std::string& readStr = read.seq;
         readStr.erase(
             std::remove_if(readStr.begin(), readStr.end(),
                            [](const char a) -> bool { return !(isprint(a)); }),
@@ -470,7 +470,7 @@ void indexTranscriptsSA(ParserT* parser, std::string& outputDir,
             if (newEndPos == std::string::npos) {
               log->warn("Entry with header [{}] appeared to be all A's; it "
                         "will be removed from the index!",
-                        j->data[i].header);
+                        read.name);
               readStr.resize(0);
             } else {
               readStr.resize(newEndPos + 1);
@@ -482,22 +482,26 @@ void indexTranscriptsSA(ParserT* parser, std::string& outputDir,
         readLen = readStr.size();
         // If the transcript was completely removed during clipping, don't
         // include it in the index.
-        if (readStr.size() >= k) {
+        if (readStr.size() > 0) {
           // If we're suspicious the user has fed in a *genome* rather
           // than a transcriptome, say so here.
           if (readStr.size() >= tooLong) {
             log->warn("Entry with header [{}] was longer than {} nucleotides.  "
                       "Are you certain that "
                       "we are indexing a transcriptome and not a genome?",
-                      j->data[i].header, tooLong);
+                      read.name, tooLong);
+          } else if (readStr.size() < k) {
+            log->warn("Entry with header [{}], had length less than "
+                      "the k-mer length of {} (perhaps after poly-A clipping)",
+                      read.name, k);
           }
 
           uint32_t txpIndex = n++;
 
           // The name of the current transcript
-          auto& recHeader = j->data[i].header;
+          auto& recHeader = read.name;
           transcriptNames.emplace_back(
-              recHeader.substr(0, recHeader.find_first_of(" \t")));
+                                       recHeader.substr(0, recHeader.find_first_of(sepStr)));//" \t")));
 
           // The position at which this transcript starts
           transcriptStarts.push_back(currIndex);
@@ -507,9 +511,9 @@ void indexTranscriptsSA(ParserT* parser, std::string& outputDir,
           currIndex += readLen + 1;
           onePos.push_back(currIndex - 1);
         } else {
-            log->warn("Discarding entry with header [{}], since it was shorter than "
-                      "the k-mer length of {} (perhaps after poly-A clipping)", 
-                      j->data[i].header, k);
+            log->warn("Discarding entry with header [{}], since it had length 0 "
+                      "(perhaps after poly-A clipping)",
+                      read.name);
         }
       }
       if (n % 10000 == 0) {
@@ -658,6 +662,10 @@ int rapMapSAIndex(int argc, char* argv[]) {
       "path");
   TCLAP::ValueArg<uint32_t> kval("k", "klen", "The length of k-mer to index",
                                  false, 31, "positive integer less than 32");
+
+  TCLAP::ValueArg<std::string> customSeps("s", "headerSep", "Instead of a space or tab, break the header at the first "
+                                          "occurrence of this string, and name the transcript as the token before "
+                                          "the first separator", false, " \t", "string");
   TCLAP::SwitchArg noClip(
       "n", "noClip",
       "Don't clip poly-A tails from the ends of target sequences", false);
@@ -674,6 +682,7 @@ int rapMapSAIndex(int argc, char* argv[]) {
   cmd.add(kval);
   cmd.add(noClip);
   cmd.add(perfectHash);
+  cmd.add(customSeps);
   cmd.add(numHashThreads);
   cmd.parse(argc, argv);
 
@@ -681,6 +690,8 @@ int rapMapSAIndex(int argc, char* argv[]) {
   std::string transcriptFile(transcripts.getValue());
   std::vector<std::string> transcriptFiles({transcriptFile});
 
+  std::string sepStr = customSeps.getValue();
+
   uint32_t k = kval.getValue();
   if (k % 2 == 0) {
     std::cerr << "Error: k must be an odd value, you chose " << k << '\n';
@@ -712,20 +723,19 @@ int rapMapSAIndex(int argc, char* argv[]) {
   auto fileLog = spdlog::create("fileLog", {fileSink});
   auto jointLog = spdlog::create("jointLog", {fileSink, consoleSink});
 
-  size_t maxReadGroup{1000}; // Number of reads in each "job"
-  size_t concurrentFile{2};  // Number of files to read simultaneously
-  size_t numThreads{2};
-  stream_manager streams(transcriptFiles.begin(), transcriptFiles.end(),
-                         concurrentFile);
+  size_t numThreads{1};
+
   std::unique_ptr<single_parser> transcriptParserPtr{nullptr};
-  transcriptParserPtr.reset(
-      new single_parser(4 * numThreads, maxReadGroup, concurrentFile, streams));
 
+  size_t numProd = 1;
+  transcriptParserPtr.reset(
+			    new single_parser(transcriptFiles, numThreads, numProd));
+  transcriptParserPtr->start();
   bool noClipPolyA = noClip.getValue();
   bool usePerfectHash = perfectHash.getValue();
   uint32_t numPerfectHashThreads = numHashThreads.getValue();
   std::mutex iomutex;
   indexTranscriptsSA(transcriptParserPtr.get(), indexDir, noClipPolyA,
-                     usePerfectHash, numPerfectHashThreads, iomutex, jointLog);
+                     usePerfectHash, numPerfectHashThreads, sepStr, iomutex, jointLog);
   return 0;
 }
diff --git a/debian/rapmap/RapMapUtils.cpp b/debian/rapmap/RapMapUtils.cpp
new file mode 100644
index 0000000..a830d05
--- /dev/null
+++ b/debian/rapmap/RapMapUtils.cpp
@@ -0,0 +1,584 @@
+#include <cereal/types/vector.hpp>
+#include <cereal/types/unordered_map.hpp>
+#include <cereal/archives/binary.hpp>
+
+#include "RapMapUtils.hpp"
+#include "RapMapSAIndex.hpp"
+#include "RapMapIndex.hpp"
+#include "PairAlignmentFormatter.hpp"
+#include "SingleAlignmentFormatter.hpp"
+//#include "jellyfish/whole_sequence_parser.hpp"
+#include "FastxParser.hpp"
+#include "BooMap.hpp"
+
+namespace rapmap {
+    namespace utils {
+        std::vector<std::string> tokenize(const std::string &s, char delim) {
+            std::stringstream ss(s);
+            std::string item;
+            std::vector<std::string> elems;
+            while (std::getline(ss, item, delim)) {
+                elems.push_back(item);
+            }
+            return elems;
+        }
+
+
+		// positions are stored in a packed format, where the highest
+		// 2-bits encode if this position refers to a new transcript
+		// and whether or not the k-mer from the hash matches this txp
+		// in the forward or rc direction.
+		void decodePosition(uint32_t p, int32_t& pOut, bool& newTxp, bool& isRC) {
+			uint32_t highBits = (p >> 30);
+			pOut = (p & 0x3fffffff);
+			newTxp = (highBits & 0x1);
+			isRC = (highBits & 0x2);
+		}
+
+
+
+        static constexpr int8_t rc_table[128] = {
+            78, 78,  78, 78,  78,  78,  78, 78,  78, 78, 78, 78,  78, 78, 78, 78, // 15
+            78, 78,  78, 78,  78,  78,  78, 78,  78, 78, 78, 78,  78, 78, 78, 78, // 31
+            78, 78,  78, 78,  78,  78,  78, 78,  78, 78, 78, 78,  78, 78, 78, 78, // 787
+            78, 78,  78, 78,  78,  78,  78, 78,  78, 78, 78, 78,  78, 78, 78, 78, // 63
+            78, 84, 78, 71, 78,  78,  78, 67, 78, 78, 78, 78,  78, 78, 78, 78, // 79
+            78, 78,  78, 78,  65, 65, 78, 78,  78, 78, 78, 78,  78, 78, 78, 78, // 95
+            78, 84, 78, 71, 78,  78,  78, 67, 78, 78, 78, 78,  78, 78, 78, 78, // 101
+            78, 78,  78, 78,  65, 65, 78, 78,  78, 78, 78, 78,  78, 78, 78, 78  // 127
+        };
+
+        // Adapted from
+        // https://github.com/mengyao/Complete-Striped-Smith-Waterman-Library/blob/8c9933a1685e0ab50c7d8b7926c9068bc0c9d7d2/src/main.c#L36
+        void reverseRead(std::string& seq,
+                std::string& qual,
+                std::string& readWork,
+                std::string& qualWork) {
+
+            readWork.resize(seq.length(), 'A');
+            qualWork.resize(qual.length(), 'I');
+            int32_t end = seq.length()-1, start = 0;
+            //readWork[end] = '\0';
+            //qualWork[end] = '\0';
+            while (LIKELY(start < end)) {
+                readWork[start] = (char)rc_table[(int8_t)seq[end]];
+                readWork[end] = (char)rc_table[(int8_t)seq[start]];
+                qualWork[start] = qual[end];
+                qualWork[end] = qual[start];
+                ++ start;
+                -- end;
+            }
+            // If odd # of bases, we still have to complement the middle
+            if (start == end) {
+                readWork[start] = (char)rc_table[(int8_t)seq[start]];
+                // but don't need to mess with quality
+                // qualWork[start] = qual[start];
+            }
+            //std::swap(seq, readWork);
+            //std::swap(qual, qualWork);
+        }
+
+        // Adapted from
+        // https://github.com/mengyao/Complete-Striped-Smith-Waterman-Library/blob/8c9933a1685e0ab50c7d8b7926c9068bc0c9d7d2/src/main.c#L36
+        // Don't modify the qual
+        void reverseRead(std::string& seq,
+                std::string& readWork) {
+
+            readWork.resize(seq.length(), 'A');
+            int32_t end = seq.length()-1, start = 0;
+            //readWork[end] = '\0';
+            //qualWork[end] = '\0';
+            while (LIKELY(start < end)) {
+                readWork[start] = (char)rc_table[(int8_t)seq[end]];
+                readWork[end] = (char)rc_table[(int8_t)seq[start]];
+                ++ start;
+                -- end;
+            }
+            // If odd # of bases, we still have to complement the middle
+            if (start == end) {
+                readWork[start] = (char)rc_table[(int8_t)seq[start]];
+                // but don't need to mess with quality
+                // qualWork[start] = qual[start];
+            }
+            //std::swap(seq, readWork);
+            //std::swap(qual, qualWork);
+        }
+
+        template <typename ReadT, typename IndexT>
+        uint32_t writeAlignmentsToStream(
+                ReadT& r,
+                SingleAlignmentFormatter<IndexT>& formatter,
+                HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& hits,
+                fmt::MemoryWriter& sstream
+                ) {
+                // Convenient variable name bindings
+                auto& txpNames = formatter.index->txpNames;
+                auto& txpLens = formatter.index->txpLens;
+
+                auto& readTemp = formatter.readTemp;
+                //auto& qualTemp = formatter.qualTemp;
+                auto& cigarStr = formatter.cigarStr;
+
+                uint16_t flags;
+
+                auto& readName = r.name;
+#if defined(__DEBUG__) || defined(__TRACK_CORRECT__)
+                auto before = readName.find_first_of(':');
+                before = readName.find_first_of(':', before+1);
+                auto after = readName.find_first_of(':', before+1);
+                const auto& txpName = readName.substr(before+1, after-before-1);
+#endif //__DEBUG__
+                // If the read name contains multiple space-separated parts, print
+                // only the first
+                size_t splitPos = readName.find(' ');
+                if (splitPos < readName.length()) {
+                    readName[splitPos] = '\0';
+                }
+
+
+                std::string numHitFlag = fmt::format("NH:i:{}", hits.size());
+                uint32_t alnCtr{0};
+                bool haveRev{false};
+                for (auto& qa : hits) {
+                    auto& transcriptName = txpNames[qa.tid];
+                    // === SAM
+                    rapmap::utils::getSamFlags(qa, flags);
+                    if (alnCtr != 0) {
+                        flags |= 0x900;
+                    }
+
+                    std::string* readSeq = &(r.seq);
+                    //std::string* qstr = &(r.qual);
+
+                    if (!qa.fwd) {
+                        if (!haveRev) {
+                            rapmap::utils::reverseRead(*readSeq, readTemp);
+                            haveRev = true;
+                        }
+                        readSeq = &(readTemp);
+                        //qstr = &(qualTemp);
+                    }
+
+                   rapmap::utils::adjustOverhang(qa.pos, qa.readLen, txpLens[qa.tid], cigarStr);
+
+                    sstream << readName.c_str() << '\t' // QNAME
+                        << flags << '\t' // FLAGS
+                        << transcriptName << '\t' // RNAME
+                        << qa.pos + 1 << '\t' // POS (1-based)
+                        << 255 << '\t' // MAPQ
+                        << cigarStr.c_str() << '\t' // CIGAR
+                        << '*' << '\t' // MATE NAME
+                        << 0 << '\t' // MATE POS
+                        << qa.fragLen << '\t' // TLEN
+                        << *readSeq << '\t' // SEQ
+                        << "*\t" // QSTR
+                        << numHitFlag << '\n';
+                    ++alnCtr;
+                    // === SAM
+#if defined(__DEBUG__) || defined(__TRACK_CORRECT__)
+                    if (txpNames[qa.tid] == txpName) { ++hctr.trueHits; }
+#endif //__DEBUG__
+                }
+                return alnCtr;
+            }
+
+        // For reads paired *in sequencing*
+        template <typename ReadPairT, typename IndexT>
+        uint32_t writeAlignmentsToStream(
+                ReadPairT& r,
+                PairAlignmentFormatter<IndexT>& formatter,
+                HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream
+                ) {
+                // Convenient variable name bindings
+                auto& txpNames = formatter.index->txpNames;
+                auto& txpLens = formatter.index->txpLens;
+
+                auto& read1Temp = formatter.read1Temp;
+                auto& read2Temp = formatter.read2Temp;
+                //auto& qual1Temp = formatter.qual1Temp;
+                //auto& qual2Temp = formatter.qual2Temp;
+                auto& cigarStr1 = formatter.cigarStr1;
+                auto& cigarStr2 = formatter.cigarStr2;
+
+                uint16_t flags1, flags2;
+
+                auto& readName = r.first.name;
+                // If the read name contains multiple space-separated parts,
+                // print only the first
+                size_t splitPos = readName.find(' ');
+                if (splitPos < readName.length()) {
+                    readName[splitPos] = '\0';
+                } else {
+                    splitPos = readName.length();
+                }
+
+                // trim /1 from the pe read
+                if (splitPos > 2 and readName[splitPos - 2] == '/') {
+                    readName[splitPos - 2] = '\0';
+                }
+
+                auto& mateName = r.second.name;
+                // If the read name contains multiple space-separated parts,
+                // print only the first
+                splitPos = mateName.find(' ');
+                if (splitPos < mateName.length()) {
+                    mateName[splitPos] = '\0';
+                } else {
+                    splitPos = mateName.length();
+                }
+
+                // trim /2 from the pe read
+                if (splitPos > 2 and mateName[splitPos - 2] == '/') {
+                    mateName[splitPos - 2] = '\0';
+                }
+
+                /*
+                // trim /1 and /2 from pe read names
+                if (readName.length() > 2 and
+                        readName[readName.length() - 2] == '/') {
+                    readName[readName.length() - 2] = '\0';
+                }
+                if (mateName.length() > 2 and
+                        mateName[mateName.length() - 2] == '/') {
+                    mateName[mateName.length() - 2] = '\0';
+                }
+                */
+
+                std::string numHitFlag = fmt::format("NH:i:{}", jointHits.size());
+                uint32_t alnCtr{0};
+				uint32_t trueHitCtr{0};
+				QuasiAlignment* firstTrueHit{nullptr};
+                bool haveRev1{false};
+                bool haveRev2{false};
+                bool* haveRev = nullptr;
+                size_t i{0};
+                for (auto& qa : jointHits) {
+
+                    ++i;
+                    auto& transcriptName = txpNames[qa.tid];
+                    // === SAM
+                    if (qa.isPaired) {
+                        rapmap::utils::getSamFlags(qa, true, flags1, flags2);
+                        if (alnCtr != 0) {
+                            flags1 |= 0x100; flags2 |= 0x100;
+                        }
+
+                        auto txpLen = txpLens[qa.tid];
+                        rapmap::utils::adjustOverhang(qa, txpLens[qa.tid], cigarStr1, cigarStr2);
+
+                        // Reverse complement the read and reverse
+                        // the quality string if we need to
+                        std::string* readSeq1 = &(r.first.seq);
+                        //std::string* qstr1 = &(r.first.qual);
+                        if (!qa.fwd) {
+                            if (!haveRev1) {
+                                rapmap::utils::reverseRead(*readSeq1, read1Temp);
+                                haveRev1 = true;
+                            }
+                            readSeq1 = &(read1Temp);
+                            //qstr1 = &(qual1Temp);
+                        }
+
+                        std::string* readSeq2 = &(r.second.seq);
+                        //std::string* qstr2 = &(r.second.qual);
+                        if (!qa.mateIsFwd) {
+                            if (!haveRev2) {
+                                rapmap::utils::reverseRead(*readSeq2, read2Temp);
+                                haveRev2 = true;
+                            }
+                            readSeq2 = &(read2Temp);
+                            //qstr2 = &(qual2Temp);
+                        }
+
+                        // If the fragment overhangs the right end of the transcript
+                        // adjust fragLen (overhanging the left end is already handled).
+                        int32_t read1Pos = qa.pos;
+                        int32_t read2Pos = qa.matePos;
+                        const bool read1First{read1Pos < read2Pos};
+                        const int32_t minPos = read1First ? read1Pos : read2Pos;
+                        if (minPos + qa.fragLen > txpLen) { qa.fragLen = txpLen - minPos; }
+                        
+                        // get the fragment length as a signed int
+                        const int32_t fragLen = static_cast<int32_t>(qa.fragLen);
+
+
+                        sstream << readName.c_str() << '\t' // QNAME
+                                << flags1 << '\t' // FLAGS
+                                << transcriptName << '\t' // RNAME
+                                << qa.pos + 1 << '\t' // POS (1-based)
+                                << 1 << '\t' // MAPQ
+                                << cigarStr1.c_str() << '\t' // CIGAR
+                                << '=' << '\t' // RNEXT
+                                << qa.matePos + 1 << '\t' // PNEXT
+                                << ((read1First) ? fragLen : -fragLen) << '\t' // TLEN
+                                << *readSeq1 << '\t' // SEQ
+                                << "*\t" // QUAL
+                                << numHitFlag << '\n';
+
+                        sstream << mateName.c_str() << '\t' // QNAME
+                                << flags2 << '\t' // FLAGS
+                                << transcriptName << '\t' // RNAME
+                                << qa.matePos + 1 << '\t' // POS (1-based)
+                                << 1 << '\t' // MAPQ
+                                << cigarStr2.c_str() << '\t' // CIGAR
+                                << '=' << '\t' // RNEXT
+                                << qa.pos + 1 << '\t' // PNEXT
+                                << ((read1First) ? -fragLen : fragLen) << '\t' // TLEN
+                                << *readSeq2 << '\t' // SEQ
+                                << "*\t" // QUAL
+                                << numHitFlag << '\n';
+                    } else {
+                        rapmap::utils::getSamFlags(qa, true, flags1, flags2);
+                        if (alnCtr != 0) {
+                            flags1 |= 0x100; flags2 |= 0x100;
+                        }
+			/*
+			else {
+                            // If this is the first alignment for this read
+                            // If the left end is mapped, set 0x100 on the right end
+                            if (qa.mateStatus == MateStatus::PAIRED_END_LEFT) {
+                                flags2 |= 0x100;
+                            } else {
+                            // Otherwise, set 0x100 on the left end
+                                flags1 |= 0x100;
+                            }
+                        }
+			*/
+
+                        std::string* readSeq{nullptr};
+                        std::string* unalignedSeq{nullptr};
+
+                        uint32_t flags, unalignedFlags;
+                        //std::string* qstr{nullptr};
+                        //std::string* unalignedQstr{nullptr};
+                        std::string* alignedName{nullptr};
+                        std::string* unalignedName{nullptr};
+                        std::string* readTemp{nullptr};
+                        //std::string* qualTemp{nullptr};
+
+                        rapmap::utils::FixedWriter* cigarStr;
+                        if (qa.mateStatus == MateStatus::PAIRED_END_LEFT) { // left read
+                            alignedName = &readName;
+                            unalignedName = &mateName;
+
+                            readSeq = &(r.first.seq);
+                            unalignedSeq = &(r.second.seq);
+
+                            //qstr = &(r.first.qual);
+                            //unalignedQstr = &(r.second.qual);
+
+                            flags = flags1;
+                            unalignedFlags = flags2;
+
+                            cigarStr = &cigarStr1;
+
+                            haveRev = &haveRev1;
+                            readTemp = &read1Temp;
+                            //qualTemp = &qual1Temp;
+                        } else { // right read
+                            alignedName = &mateName;
+                            unalignedName = &readName;
+
+                            readSeq = &(r.second.seq);
+                            unalignedSeq = &(r.first.seq);
+
+                            //qstr = &(r.second.qual);
+                            //unalignedQstr = &(r.first.qual);
+
+                            flags = flags2;
+                            unalignedFlags = flags1;
+
+                            cigarStr = &cigarStr2;
+                            haveRev = &haveRev2;
+                            readTemp = &read2Temp;
+                            //qualTemp = &qual2Temp;
+                        }
+
+                        // Reverse complement the read and reverse
+                        // the quality string if we need to
+                        if (!qa.fwd) {
+                            if (!(*haveRev)) {
+                                rapmap::utils::reverseRead(*readSeq, *readTemp);
+                                *haveRev = true;
+                            }
+                            readSeq = readTemp;
+                        }
+
+                        /*
+                        if (!qa.fwd) {
+                            rapmap::utils::reverseRead(*readSeq, *qstr,
+                                        read1Temp, qual1Temp);
+                        }
+                        */
+
+                        rapmap::utils::adjustOverhang(qa.pos, qa.readLen, txpLens[qa.tid], *cigarStr);
+                        sstream << alignedName->c_str() << '\t' // QNAME
+                                << flags << '\t' // FLAGS
+                                << transcriptName << '\t' // RNAME
+                                << qa.pos + 1 << '\t' // POS (1-based)
+                                << 1 << '\t' // MAPQ
+                                << cigarStr->c_str() << '\t' // CIGAR
+                                << '=' << '\t' // RNEXT
+                                << qa.pos+1 << '\t' // PNEXT (only 1 read in templte)
+                                << 0 << '\t' // TLEN (spec says 0, not read len)
+                                << *readSeq << '\t' // SEQ
+                                << "*\t" // QUAL
+                                << numHitFlag << '\n';
+
+
+                        // Output the info for the unaligned mate.
+                        sstream << unalignedName->c_str() << '\t' // QNAME
+                            << unalignedFlags << '\t' // FLAGS
+                            << transcriptName << '\t' // RNAME (same as mate)
+                            << qa.pos + 1 << '\t' // POS (same as mate)
+                            << 0 << '\t' // MAPQ
+                            << unalignedSeq->length() << 'S' << '\t' // CIGAR
+                            << '=' << '\t' // RNEXT
+                            << qa.pos + 1 << '\t' // PNEXT (only 1 read in template)
+                            << 0 << '\t' // TLEN (spec says 0, not read len)
+                            << *unalignedSeq << '\t' // SEQ
+                            << "*\t" // QUAL
+                            << numHitFlag << '\n';
+                    }
+                    ++alnCtr;
+                    // == SAM
+#if defined(__DEBUG__) || defined(__TRACK_CORRECT__)
+                    if (transcriptName == trueTxpName) {
+							if (trueHitCtr == 0) {
+									++hctr.trueHits;
+									++trueHitCtr;
+									firstTrueHit = &qa;
+							} else {
+									++trueHitCtr;
+									std::cerr << "Found true hit " << trueHitCtr << " times!\n";
+									std::cerr << transcriptName << '\t' << firstTrueHit->pos
+											<< '\t' << firstTrueHit->fwd << '\t' << firstTrueHit->fragLen
+											<< '\t' << (firstTrueHit->isPaired ? "Paired" : "Orphan") << '\t';
+								    printMateStatus(firstTrueHit->mateStatus);
+								    std::cerr << '\n';
+									std::cerr << transcriptName << '\t' << qa.pos
+											  << '\t' << qa.fwd << '\t' << qa.fragLen
+										      << '\t' << (qa.isPaired ? "Paired" : "Orphan") << '\t';
+								    printMateStatus(qa.mateStatus);
+								    std::cerr << '\n';
+							}
+					}
+#endif //__DEBUG__
+                }
+                return alnCtr;
+        }
+
+
+
+        // Is there a smarter way to do save / load here?
+        /*
+        template <typename Archive, typename MerT>
+            void save(Archive& archive, const MerT& mer) const {
+                auto key = mer.get_bits(0, 2*mer.k());
+                archive(key);
+            }
+
+        template <typename Archive>
+            void load(Archive& archive, const MerT& mer) {
+                mer.polyT();
+                uint64_t bits;
+                archive(bits);
+                auto k = mer.k();
+                mer.set_bits(0, 2*k, bits);
+            }
+        */
+    }
+}
+
+using SAIndex32BitDense = RapMapSAIndex<int32_t,google::dense_hash_map<uint64_t, rapmap::utils::SAInterval<int32_t>,
+								       rapmap::utils::KmerKeyHasher>>;
+using SAIndex64BitDense = RapMapSAIndex<int64_t,google::dense_hash_map<uint64_t, rapmap::utils::SAInterval<int64_t>,
+								       rapmap::utils::KmerKeyHasher>>;
+using SAIndex32BitPerfect = RapMapSAIndex<int32_t, BooMap<uint64_t, rapmap::utils::SAInterval<int32_t>>>;
+using SAIndex64BitPerfect = RapMapSAIndex<int64_t, BooMap<uint64_t, rapmap::utils::SAInterval<int64_t>>>;
+
+// Explicit instantiations
+// pair parser, 32-bit, dense hash
+template uint32_t rapmap::utils::writeAlignmentsToStream<fastx_parser::ReadPair, SAIndex32BitDense*>(
+                fastx_parser::ReadPair& r,
+                PairAlignmentFormatter<SAIndex32BitDense*>& formatter,
+                rapmap::utils::HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream);
+
+// pair parser, 64-bit, dense hash
+template uint32_t rapmap::utils::writeAlignmentsToStream<fastx_parser::ReadPair, SAIndex64BitDense*>(
+                fastx_parser::ReadPair& r,
+                PairAlignmentFormatter<SAIndex64BitDense*>& formatter,
+                rapmap::utils::HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream);
+
+// pair parser, 32-bit, perfect hash
+template uint32_t rapmap::utils::writeAlignmentsToStream<fastx_parser::ReadPair, SAIndex32BitPerfect*>(
+                fastx_parser::ReadPair& r,
+                PairAlignmentFormatter<SAIndex32BitPerfect*>& formatter,
+                rapmap::utils::HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream);
+
+// pair parser, 64-bit, perfect hash
+template uint32_t rapmap::utils::writeAlignmentsToStream<fastx_parser::ReadPair, SAIndex64BitPerfect*>(
+                fastx_parser::ReadPair& r,
+                PairAlignmentFormatter<SAIndex64BitPerfect*>& formatter,
+                rapmap::utils::HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream);
+
+
+// single parser, 32-bit, dense hash
+template uint32_t rapmap::utils::writeAlignmentsToStream<fastx_parser::ReadSeq, SAIndex32BitDense*>(
+		fastx_parser::ReadSeq& r,
+                SingleAlignmentFormatter<SAIndex32BitDense*>& formatter,
+                rapmap::utils::HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream);
+
+// single parser, 64-bit, dense hash
+template uint32_t rapmap::utils::writeAlignmentsToStream<fastx_parser::ReadSeq, SAIndex64BitDense*>(
+		fastx_parser::ReadSeq& r,
+                SingleAlignmentFormatter<SAIndex64BitDense*>& formatter,
+                rapmap::utils::HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream);
+
+// single parser, 32-bit, perfect hash
+template uint32_t rapmap::utils::writeAlignmentsToStream<fastx_parser::ReadSeq, SAIndex32BitPerfect*>(
+ 		fastx_parser::ReadSeq& r,
+                SingleAlignmentFormatter<SAIndex32BitPerfect*>& formatter,
+                rapmap::utils::HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream);
+
+// single parser, 64-bit, perfect hash
+template uint32_t rapmap::utils::writeAlignmentsToStream<fastx_parser::ReadSeq, SAIndex64BitPerfect*>(
+		fastx_parser::ReadSeq& r,
+                SingleAlignmentFormatter<SAIndex64BitPerfect*>& formatter,
+                rapmap::utils::HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream);
+
+
+template uint32_t rapmap::utils::writeAlignmentsToStream<fastx_parser::ReadPair, RapMapIndex*>(
+                fastx_parser::ReadPair& r,
+                PairAlignmentFormatter<RapMapIndex*>& formatter,
+                rapmap::utils::HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream
+                );
+
+template uint32_t rapmap::utils::writeAlignmentsToStream<fastx_parser::ReadSeq, RapMapIndex*>(
+                fastx_parser::ReadSeq& r,
+                SingleAlignmentFormatter<RapMapIndex*>& formatter,
+                rapmap::utils::HitCounters& hctr,
+                std::vector<rapmap::utils::QuasiAlignment>& jointHits,
+                fmt::MemoryWriter& sstream
+                );
diff --git a/debian/rapmap/RapMapUtils.hpp b/debian/rapmap/RapMapUtils.hpp
index cbae039..7f2fef3 100644
--- a/debian/rapmap/RapMapUtils.hpp
+++ b/debian/rapmap/RapMapUtils.hpp
@@ -8,7 +8,8 @@
 #include <cereal/archives/binary.hpp>
 #include "jellyfish/mer_dna.hpp"
 #include "spdlog/spdlog.h"
-#include "spdlog/fmt/bundled/format.h"
+#include "spdlog/fmt/ostr.h"
+#include "spdlog/fmt/fmt.h"
 #include "PairSequenceParser.hpp"
 
 #ifdef RAPMAP_SALMON_SUPPORT
@@ -49,7 +50,7 @@ namespace rapmap {
     template <typename IndexT>
         void writeSAMHeader(IndexT& rmi, std::shared_ptr<spdlog::logger> out) {
             fmt::MemoryWriter hd;
-            hd.write("@HD\tVN:0.1\tSO:unknown\n");
+	    hd.write("@HD\tVN:1.0\tSO:unknown\n");
 
             auto& txpNames = rmi.txpNames;
             auto& txpLens = rmi.txpLens;
@@ -58,18 +59,18 @@ namespace rapmap {
             for (size_t i = 0; i < numRef; ++i) {
                 hd.write("@SQ\tSN:{}\tLN:{:d}\n", txpNames[i], txpLens[i]);
             }
-            // Eventuall output a @PG line
-            //hd.format("@PG\t");
+            // Eventually output a @PG line
+            hd.write("@PG\tID:rapmap\tPN:rapmap\tVN:0.3.1\n");
             std::string headerStr(hd.str());
             // Don't include the last '\n', since the logger will do it for us.
             headerStr.pop_back();
-            out->info("%s", headerStr);
+            out->info(headerStr);
         }
 
     template <typename IndexT>
         void writeSAMHeader(IndexT& rmi, std::ostream& outStream) {
             fmt::MemoryWriter hd;
-            hd.write("@HD\tVN:0.1\tSO:unknown\n");
+	    hd.write("@HD\tVN:1.0\tSO:unknown\n");
 
             auto& txpNames = rmi.txpNames;
             auto& txpLens = rmi.txpLens;
@@ -78,8 +79,8 @@ namespace rapmap {
             for (size_t i = 0; i < numRef; ++i) {
                 hd.write("@SQ\tSN:{}\tLN:{:d}\n", txpNames[i], txpLens[i]);
             }
-            // Eventuall output a @PG line
-            //hd.format("@PG\t");
+            // Eventually output a @PG line
+            hd.write("@PG\tID:rapmap\tPN:rapmap\tVN:0.3.1\n");
             outStream << hd.str();
         }
 
@@ -299,8 +300,9 @@ namespace rapmap {
 #ifdef RAPMAP_SALMON_SUPPORT
         inline uint32_t transcriptID() const { return tid; }
         inline double score() { return 1.0; }
-        inline uint32_t fragLength() { return fragLen; }
-        inline uint32_t fragLengthPedantic(uint32_t txpLen) const { 
+        inline uint32_t fragLength() const { return fragLen; }
+
+        inline uint32_t fragLengthPedantic(uint32_t txpLen) const {
             if (mateStatus != rapmap::utils::MateStatus::PAIRED_END_PAIRED
                 or fwd == mateIsFwd) {
                 return 0;
@@ -314,6 +316,7 @@ namespace rapmap {
 
             return (p1 > p2) ? p1 - p2 : p2 - p1;
         }
+
         inline int32_t hitPos() { return std::min(pos, matePos); }
         double logProb{HUGE_VAL};
         double logBias{HUGE_VAL};
@@ -387,10 +390,10 @@ namespace rapmap {
          * This enforces a more stringent consistency check on
          * the hits for this transcript.  The hits must be co-linear
          * with respect to the query and target.
-         * 
+         *
          * input: numToCheck --- the number of hits to check in sorted order
          *                       hits after the last of these need not be consistent.
-         * return: numToCheck if the first numToCheck hits are consistent; 
+         * return: numToCheck if the first numToCheck hits are consistent;
          *         -1 otherwise
          **/
         int32_t checkConsistent(int32_t numToCheck) {
@@ -405,7 +408,7 @@ namespace rapmap {
                 return (h2.pos > h1.pos) ? (numToCheck) : -1;
             } else {
                 // first, sort by query position
-                std::sort(tqvec.begin(), tqvec.end(), 
+                std::sort(tqvec.begin(), tqvec.end(),
                           [](const SATxpQueryPos& q1, const SATxpQueryPos& q2) -> bool {
                               return q1.queryPos < q2.queryPos;
                           });
@@ -699,7 +702,7 @@ namespace rapmap {
                                 int32_t startRead2 = std::max(rightIt->pos, signedZero);
                                 bool read1First{(startRead1 < startRead2)};
                                 int32_t fragStartPos = read1First ? startRead1 : startRead2;
-                                int32_t fragEndPos = read1First ? 
+                                int32_t fragEndPos = read1First ?
                                     (startRead2 + rightIt->readLen) : (startRead1 + leftIt->readLen);
                                 uint32_t fragLen = fragEndPos - fragStartPos;
                                 jointHits.emplace_back(leftTxp,
@@ -763,7 +766,7 @@ namespace rapmap {
                                 int32_t startRead2 = std::max(rightIt->pos, signedZero);
                                 bool read1First{(startRead1 < startRead2)};
                                 int32_t fragStartPos = read1First ? startRead1 : startRead2;
-                                int32_t fragEndPos = read1First ? 
+                                int32_t fragEndPos = read1First ?
                                     (startRead2 + rightIt->readLen) : (startRead1 + leftIt->readLen);
                                 uint32_t fragLen = fragEndPos - fragStartPos;
                                 jointHits.emplace_back(leftTxp,
diff --git a/debian/rapmap/SingleAlignmentFormatter.hpp b/debian/rapmap/SingleAlignmentFormatter.hpp
new file mode 100644
index 0000000..2510082
--- /dev/null
+++ b/debian/rapmap/SingleAlignmentFormatter.hpp
@@ -0,0 +1,22 @@
+#ifndef __SINGLE_ALIGNMENT_FORMATTER_HPP__
+#define __SINGLE_ALIGNMENT_FORMATTER_HPP__
+
+#include "RapMapUtils.hpp"
+
+template <typename IndexPtrT>
+struct SingleAlignmentFormatter {
+    SingleAlignmentFormatter(IndexPtrT indexIn) : index(indexIn),
+    readTemp(1000, 'A'),
+    qualTemp(1000, '~'),
+    cigarStr(buff, 1000){
+    }
+
+    // Data members
+    IndexPtrT index;
+    std::string readTemp;
+    std::string qualTemp;
+    char buff[1000];
+    rapmap::utils::FixedWriter cigarStr;
+};
+
+#endif //__PAIR_ALIGNMENT_FORMATTER_HPP__
diff --git a/debian/rules b/debian/rules
index 16364bf..442ae38 100755
--- a/debian/rules
+++ b/debian/rules
@@ -12,7 +12,7 @@ VERSION        := $(shell echo '$(DEBVERS)' | sed -e 's/^[0-9]*://' -e 's/-.*//'
 	dh $@ --with sphinxdoc --parallel
 
 override_dh_auto_configure:
-	cp -v debian/rapmap/RapMap* \
+	cp -v debian/rapmap/RapMap*.h* \
               debian/rapmap/Boo???.hpp \
               debian/rapmap/IndexHeader.hpp \
               debian/rapmap/HitManager.hpp \
@@ -24,11 +24,12 @@ override_dh_auto_configure:
               debian/rapmap/bit_*.h \
               debian/rapmap/rank9b.h \
               debian/rapmap/macros.h \
+	      debian/rapmap/PairAlignmentFormatter.hpp \
+	      debian/rapmap/SingleAlignmentFormatter.hpp \
               include/
 	cp -v debian/rapmap/bit_array.c \
               debian/rapmap/rank9b.cpp \
-              debian/rapmap/RapMapSA*.cpp \
-	      debian/rapmap/RapMapFileSystem.cpp \
+              debian/rapmap/RapMap*.cpp \
 	      debian/rapmap/HitManager.cpp \
               src/
 	dh_auto_configure
@@ -48,7 +49,7 @@ override_dh_auto_build:
 
 override_dh_auto_clean:
 	dh_auto_clean
-	rm -f include/RapMap* \
+	rm -f include/RapMap*.h* \
 	      include/Boo???.hpp \
 	      include/IndexHeader.hpp \
 	      include/HitManager.hpp \
@@ -59,11 +60,12 @@ override_dh_auto_clean:
 	      include/rank9b.h \
 	      include/macros.h \
 	      include/SpinLock.hpp \
-	      include/ScopedTimer.hpp
+	      include/ScopedTimer.hpp \
+	      include/PairAlignmentFormatter.hpp \
+	      include/SingleAlignmentFormatter.hpp
 	rm -f src/bit_array.c \
               src/rank9b.cpp \
-	      src/RapMapSA*.cpp \
-	      src/RapMapFileSystem.cpp \
+	      src/RapMap*.cpp \
 	      src/HitManager.cpp
 	rm -f debian/*.1
 	rm -Rf sample_data

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/salmon.git



More information about the debian-med-commit mailing list