1 #include "Util.h"
2 #include "Parameters.h"
3 #include "Matcher.h"
4 #include "Debug.h"
5 #include "DBReader.h"
6 #include "DBWriter.h"
7 #include "Orf.h"
8 #include "AlignmentSymmetry.h"
9 #include "Timer.h"
10 #include "IndexReader.h"
11 #include "FileUtil.h"
12 
13 #ifdef OPENMP
14 #include <omp.h>
15 #endif
16 
17 
chainAlignmentHits(std::vector<Matcher::result_t> & results,std::vector<Matcher::result_t> & tmp)18 void chainAlignmentHits(std::vector<Matcher::result_t> &results, std::vector<Matcher::result_t> &tmp) {
19     if(results.size() > 1){
20         std::stable_sort(results.begin(), results.end(), Matcher::compareHitsByPosAndStrand);
21         int prevDiagonal = INT_MAX;
22         Matcher::result_t  currRegion;
23         currRegion.dbKey = UINT_MAX;
24         for (size_t resIdx = 0; resIdx < results.size(); resIdx++) {
25             bool currQueryStrang = (results[resIdx].qStartPos > results[resIdx].qEndPos);
26             int qStartPos = std::min(results[resIdx].qStartPos,  results[resIdx].qEndPos);
27             int qEndPos = std::max(results[resIdx].qStartPos,  results[resIdx].qEndPos);
28             bool currTargetStrand = (results[resIdx].dbStartPos > results[resIdx].dbEndPos);
29             int dbStartPos = std::min(results[resIdx].dbStartPos, results[resIdx].dbEndPos);
30             int dbEndPos = std::max(results[resIdx].dbStartPos, results[resIdx].dbEndPos);
31             std::cout << results[resIdx].dbKey<< "\t" << qStartPos<< "\t" << qEndPos<< "\t" << dbStartPos<< "\t" << dbEndPos << "\t" << std::endl;
32             if(currRegion.dbKey == UINT_MAX){
33                 currRegion = results[resIdx];
34                 currRegion.qStartPos = qStartPos;
35                 currRegion.qEndPos = qEndPos;
36                 currRegion.dbStartPos = dbStartPos;
37                 currRegion.dbEndPos = dbEndPos;
38             }
39             int currDiagonal = qStartPos - dbStartPos;
40             int nextDiagonal = INT_MAX;
41             bool nextQueryStrand = true;
42             bool nextTargetStrand = true;
43             const bool isDifferentKey = (currRegion.dbKey != results[resIdx].dbKey);
44             const bool isLastElement  = (resIdx == results.size() - 1);
45             if (isLastElement == false) {
46                 int nextqStartPos = std::min(results[resIdx+1].qStartPos,  results[resIdx+1].qEndPos);
47                 int nextdbStartPos = std::min(results[resIdx+1].dbStartPos, results[resIdx+1].dbEndPos);
48                 nextDiagonal = nextqStartPos - nextdbStartPos;
49                 nextQueryStrand =  (results[resIdx+1].qStartPos > results[resIdx+1].qEndPos);
50                 nextTargetStrand =  (results[resIdx+1].dbStartPos > results[resIdx+1].dbEndPos);
51             }
52             const bool queryIsOverlapping  = currRegion.qEndPos >= qStartPos   && currRegion.qEndPos <= qEndPos;
53             const bool targetIsOverlapping = currRegion.dbEndPos >= dbStartPos && currRegion.dbEndPos <= dbEndPos;
54             const bool sameNextDiagonal = (currDiagonal == nextDiagonal);
55             const bool samePrevDiagonal = (currDiagonal == prevDiagonal);
56             if ( (sameNextDiagonal || samePrevDiagonal ) && queryIsOverlapping && targetIsOverlapping) {
57                 currRegion.qStartPos = std::min(currRegion.qStartPos, qStartPos);
58                 currRegion.qEndPos = std::max(currRegion.qEndPos,  qEndPos);
59                 currRegion.dbStartPos  = std::min(currRegion.dbStartPos, dbStartPos);
60                 currRegion.dbEndPos  = std::max(currRegion.dbEndPos, dbEndPos);
61             }
62 
63             prevDiagonal = currDiagonal;
64             bool isDifferentNextDiagonal = (nextDiagonal != currDiagonal);
65             bool isDifferentStrand = (nextQueryStrand != currQueryStrang ) || (nextTargetStrand != currTargetStrand );
66             if(isDifferentKey || isLastElement || isDifferentNextDiagonal || isDifferentStrand){
67                 if(currQueryStrang){
68                     std::swap(currRegion.qStartPos, currRegion.qEndPos);
69                 }
70                 if(currTargetStrand) {
71                     std::swap(currRegion.dbStartPos, currRegion.dbEndPos);
72                 }
73                 tmp.push_back(currRegion);
74                 currRegion.dbKey = UINT_MAX;
75             }
76         }
77     }
78 }
79 
80 //
81 
82 // We have serval options to consider
83 // Update query and target
84 //   Nucl/Nucl
85 //   TransNucl/TransNucl
86 // target update
87 //   Prot/Nucl
88 // query update
89 //   Nucl/Prot
updateOffset(char * data,std::vector<Matcher::result_t> & results,const Orf::SequenceLocation * qloc,IndexReader & tOrfDBr,bool targetNeedsUpdate,bool isNucleotideSearch,int thread_idx)90 void updateOffset(char* data, std::vector<Matcher::result_t> &results, const Orf::SequenceLocation *qloc,
91                   IndexReader& tOrfDBr, bool targetNeedsUpdate, bool isNucleotideSearch, int thread_idx) {
92     size_t startPos = results.size();
93     Matcher::readAlignmentResults(results, data, true);
94     size_t endPos = results.size();
95     for (size_t i = startPos; i < endPos; i++) {
96         Matcher::result_t &res = results[i];
97         res.queryOrfStartPos = -1;
98         res.queryOrfEndPos = -1;
99         res.dbOrfStartPos = -1;
100         res.dbOrfEndPos = -1;
101         if (targetNeedsUpdate == true || qloc == NULL) {
102             size_t targetId = tOrfDBr.sequenceReader->getId(res.dbKey);
103             char *header = tOrfDBr.sequenceReader->getData(targetId, thread_idx);
104 
105             Orf::SequenceLocation tloc = Orf::parseOrfHeader(header);
106             res.dbKey   = (tloc.id != UINT_MAX) ? tloc.id : res.dbKey;
107             size_t from = (tloc.id != UINT_MAX) ? tloc.from : (tloc.strand == Orf::STRAND_MINUS) ? res.dbLen - 1 : 0;
108 
109             int dbStartPos = isNucleotideSearch ? res.dbStartPos : res.dbStartPos * 3;
110             int dbEndPos   = isNucleotideSearch ? res.dbEndPos : res.dbEndPos * 3;
111             res.dbOrfStartPos = from;
112             res.dbOrfEndPos = tloc.to;
113             if (tloc.strand == Orf::STRAND_MINUS) {
114                 res.dbStartPos = from - dbStartPos;
115                 res.dbEndPos   = from - dbEndPos;
116                 // account for last orf
117                 //  GGCACC
118                 //  GGCA
119                 //     ^
120                 //     last codon position
121                 //  GGCACC
122                 //    GGCA
123                 //    ^
124                 //     last codon position
125                 if(isNucleotideSearch == false){
126                     res.dbEndPos = res.dbEndPos - 2;
127                 }
128             } else {
129                 res.dbStartPos = from + dbStartPos;
130                 res.dbEndPos   = from + dbEndPos;
131                 if(isNucleotideSearch == false){
132                     res.dbEndPos = res.dbEndPos + 2;
133                 }
134             }
135         }
136         if (qloc != NULL) {
137             int qStartPos = isNucleotideSearch ? res.qStartPos : res.qStartPos * 3;
138             int qEndPos   = isNucleotideSearch ? res.qEndPos : res.qEndPos * 3;
139 
140             size_t from = (qloc->id != UINT_MAX) ? qloc->from : (qloc->strand == Orf::STRAND_MINUS) ? 0 : res.qLen - 1;
141             res.queryOrfStartPos = from;
142             res.queryOrfEndPos =  qloc->to;
143 
144             if (qloc->strand == Orf::STRAND_MINUS && qloc->id != UINT_MAX) {
145                 res.qStartPos  = from - qStartPos;
146                 res.qEndPos    = from - qEndPos;
147                 if(isNucleotideSearch == false){
148                     res.qEndPos = res.qEndPos - 2;
149                 }
150             } else {
151                 res.qStartPos  = from + qStartPos;
152                 res.qEndPos    = from + qEndPos;
153                 if(isNucleotideSearch == false){
154                     res.qEndPos = res.qEndPos + 2;
155                 }
156             }
157         }
158     }
159 }
160 
updateLengths(std::vector<Matcher::result_t> & results,unsigned int qSourceLen,IndexReader * tSourceDbr)161 void updateLengths(std::vector<Matcher::result_t> &results, unsigned int qSourceLen, IndexReader* tSourceDbr) {
162     for (size_t i = 0; i < results.size(); ++i) {
163         Matcher::result_t &res = results[i];
164         if (qSourceLen != UINT_MAX) {
165             res.qLen = qSourceLen;
166         }
167         if (tSourceDbr != NULL) {
168             size_t targetId = tSourceDbr->sequenceReader->getId(res.dbKey);
169             res.dbLen = tSourceDbr->sequenceReader->getSeqLen(targetId);
170         }
171     }
172 }
173 
offsetalignment(int argc,const char ** argv,const Command & command)174 int offsetalignment(int argc, const char **argv, const Command &command) {
175     Parameters &par = Parameters::getInstance();
176     par.parseParameters(argc, argv, command, true, 0, 0);
177 
178     const bool touch = par.preloadMode != Parameters::PRELOAD_MODE_MMAP;
179     int queryDbType = FileUtil::parseDbType(par.db1.c_str());
180     if(Parameters::isEqualDbtype(queryDbType, Parameters::DBTYPE_INDEX_DB)){
181         DBReader<unsigned int> idxdbr(par.db1.c_str(), par.db1Index.c_str(), 1, DBReader<unsigned int>::USE_INDEX | DBReader<unsigned int>::USE_DATA);
182         idxdbr.open(DBReader<unsigned int>::NOSORT);
183         PrefilteringIndexData data = PrefilteringIndexReader::getMetadata(&idxdbr);
184         queryDbType=data.srcSeqType;
185         idxdbr.close();
186     }
187     int targetDbType = FileUtil::parseDbType(par.db3.c_str());
188     if(Parameters::isEqualDbtype(targetDbType, Parameters::DBTYPE_INDEX_DB)){
189         DBReader<unsigned int> idxdbr(par.db3.c_str(), par.db3Index.c_str(), 1, DBReader<unsigned int>::USE_INDEX | DBReader<unsigned int>::USE_DATA);
190         idxdbr.open(DBReader<unsigned int>::NOSORT);
191         PrefilteringIndexData data = PrefilteringIndexReader::getMetadata(&idxdbr);
192         targetDbType=data.srcSeqType;
193         idxdbr.close();
194     }
195 
196     IndexReader qOrfDbr(par.db2.c_str(), par.threads, IndexReader::HEADERS, (touch) ? (IndexReader::PRELOAD_INDEX | IndexReader::PRELOAD_DATA) : 0);
197     if (queryDbType == -1) {
198         Debug(Debug::ERROR) << "Please recreate your database or add a .dbtype file to your sequence/profile database.\n";
199         return EXIT_FAILURE;
200     }
201     const bool queryNucl = Parameters::isEqualDbtype(queryDbType, Parameters::DBTYPE_NUCLEOTIDES);
202     IndexReader *qSourceDbr = NULL;
203     if (queryNucl) {
204         qSourceDbr = new IndexReader(par.db1.c_str(), par.threads, IndexReader::SRC_SEQUENCES, (touch) ? (IndexReader::PRELOAD_INDEX) : 0, DBReader<unsigned int>::USE_INDEX);
205     }
206 
207     IndexReader * tOrfDbr;
208     bool isSameOrfDB = (par.db2.compare(par.db4) == 0);
209     if(isSameOrfDB){
210         tOrfDbr = &qOrfDbr;
211     }else{
212         tOrfDbr = new IndexReader(par.db4.c_str(), par.threads, IndexReader::HEADERS, (touch) ? (IndexReader::PRELOAD_INDEX | IndexReader::PRELOAD_DATA) : 0);
213     }
214 
215     if (targetDbType == -1) {
216         Debug(Debug::ERROR) << "Please recreate your database or add a .dbtype file to your sequence/profile database.\n";
217         return EXIT_FAILURE;
218     }
219     const bool targetNucl = Parameters::isEqualDbtype(targetDbType, Parameters::DBTYPE_NUCLEOTIDES);
220     IndexReader *tSourceDbr = NULL;
221     bool isSameSrcDB = (par.db3.compare(par.db1) == 0);
222     bool isNuclNuclSearch = false;
223     bool isTransNucTransNucSearch = false;
224     bool isTransNuclAln = false;
225     if (targetNucl) {
226         bool seqtargetNuc = true;
227         if(isSameSrcDB){
228             tSourceDbr = qSourceDbr;
229         }else{
230             tSourceDbr = new IndexReader(par.db3.c_str(), par.threads, IndexReader::SRC_SEQUENCES, (touch) ? IndexReader::PRELOAD_INDEX : 0, DBReader<unsigned int>::USE_INDEX );
231         }
232 
233         if(Parameters::isEqualDbtype(tSourceDbr->getDbtype(), Parameters::DBTYPE_INDEX_DB)){
234             IndexReader tseqDbr(par.db3, par.threads, IndexReader::SEQUENCES, 0, IndexReader::PRELOAD_INDEX);
235             seqtargetNuc = Parameters::isEqualDbtype(tseqDbr.sequenceReader->getDbtype(), Parameters::DBTYPE_NUCLEOTIDES);
236             isTransNucTransNucSearch = Parameters::isEqualDbtype(tseqDbr.sequenceReader->getDbtype(), Parameters::DBTYPE_AMINO_ACIDS);
237             if(par.searchType == Parameters::SEARCH_TYPE_TRANS_NUCL_ALN){
238                 isTransNuclAln = true;
239             }
240         }else{
241             if(par.searchType == Parameters::SEARCH_TYPE_AUTO && (targetNucl == true && queryNucl == true )){
242                 Debug(Debug::WARNING) << "Assume that nucleotide search was performed\n";
243                 Debug(Debug::WARNING) << "If this is not correct than please provide the parameter --search-type 2 (translated) or 3 (nucleotide)\n";
244             } else if(par.searchType == Parameters::SEARCH_TYPE_TRANSLATED){
245                 seqtargetNuc = false;
246                 isTransNucTransNucSearch = true;
247             } else if(par.searchType == Parameters::SEARCH_TYPE_NUCLEOTIDES){
248                 seqtargetNuc = true;
249                 isTransNucTransNucSearch = false;
250             } else if(par.searchType == Parameters::SEARCH_TYPE_TRANS_NUCL_ALN){
251                 isTransNuclAln = true;
252                 seqtargetNuc = false;
253                 isTransNucTransNucSearch = true;
254             }
255         }
256 
257         isNuclNuclSearch = (queryNucl && targetNucl && seqtargetNuc);
258     }
259 
260     DBReader<unsigned int> alnDbr(par.db5.c_str(), par.db5Index.c_str(), par.threads, DBReader<unsigned int>::USE_INDEX|DBReader<unsigned int>::USE_DATA);
261     alnDbr.open(DBReader<unsigned int>::LINEAR_ACCCESS);
262 
263 #ifdef OPENMP
264     unsigned int totalThreads = par.threads;
265 #else
266     unsigned int totalThreads = 1;
267 #endif
268 
269     unsigned int localThreads = totalThreads;
270     if (alnDbr.getSize() <= totalThreads) {
271         localThreads = alnDbr.getSize();
272     }
273 
274     // Compute mapping from contig -> orf[] from orf[]->contig in headers
275     unsigned int *contigLookup = NULL;
276     unsigned int *contigOffsets = NULL;
277     char *contigExists = NULL;
278     unsigned int maxContigKey = 0;
279     if (Parameters::isEqualDbtype(queryDbType, Parameters::DBTYPE_NUCLEOTIDES)) {
280         Timer timer;
281         Debug(Debug::INFO) << "Computing ORF lookup\n";
282         unsigned int maxOrfKey = alnDbr.getLastKey();
283         unsigned int *orfLookup = new unsigned int[maxOrfKey + 2]();
284 #pragma omp parallel num_threads(localThreads)
285         {
286             unsigned int thread_idx = 0;
287 #ifdef OPENMP
288             thread_idx = (unsigned int) omp_get_thread_num();
289 #endif
290 #pragma omp for schedule(dynamic, 10)
291             for (size_t i = 0; i <= maxOrfKey; ++i) {
292                 size_t queryId = qOrfDbr.sequenceReader->getId(i);
293                 if (queryId == UINT_MAX) {
294                     orfLookup[i] = UINT_MAX;
295                     continue;
296                 }
297                 unsigned int queryKey = qOrfDbr.sequenceReader->getDbKey(queryId);
298                 char *header = qOrfDbr.sequenceReader->getData(queryId, thread_idx);
299                 Orf::SequenceLocation qloc = Orf::parseOrfHeader(header);
300                 unsigned int id = (qloc.id != UINT_MAX) ? qloc.id : queryKey;
301                 orfLookup[i] = id;
302             }
303         }
304         Debug(Debug::INFO) << "Computing contig offsets\n";
305         maxContigKey = qSourceDbr->sequenceReader->getLastKey();
306         unsigned int *contigSizes = new unsigned int[maxContigKey + 2]();
307 #pragma omp parallel for schedule(static) num_threads(localThreads)
308         for (size_t i = 0; i <= maxOrfKey ; ++i) {
309             if(orfLookup[i] == UINT_MAX){
310                 continue;
311             }
312             __sync_fetch_and_add(&(contigSizes[orfLookup[i]]), 1);
313         }
314         contigOffsets = contigSizes;
315 
316         AlignmentSymmetry::computeOffsetFromCounts(contigOffsets, maxContigKey + 1);
317 
318         contigExists = new char[maxContigKey + 1]();
319 #pragma omp parallel for schedule(static) num_threads(localThreads)
320         for (size_t i = 0; i < qSourceDbr->sequenceReader->getSize(); ++i) {
321             contigExists[qSourceDbr->sequenceReader->getDbKey(i)] = 1;
322         }
323 
324         Debug(Debug::INFO) << "Computing contig lookup\n";
325         contigLookup = new unsigned int[maxOrfKey + 2]();
326 #pragma omp parallel for schedule(static) num_threads(localThreads)
327         for (size_t i = 0; i <= maxOrfKey; ++i) {
328             if(orfLookup[i] == UINT_MAX){
329                 continue;
330             }
331             size_t offset = __sync_fetch_and_add(&(contigOffsets[orfLookup[i]]), 1);
332             contigLookup[offset] = i;
333         }
334         delete[] orfLookup;
335 
336         for (unsigned int i = maxContigKey + 1; i > 0; --i) {
337             contigOffsets[i] = contigOffsets[i - 1];
338         }
339         contigOffsets[0] = 0;
340         Debug(Debug::INFO) << "Time for contig lookup: " << timer.lap() << "\n";
341     }
342 
343     Debug(Debug::INFO) << "Writing results to: " << par.db6 << "\n";
344     DBWriter resultWriter(par.db6.c_str(), par.db6Index.c_str(), localThreads, par.compressed, Parameters::DBTYPE_ALIGNMENT_RES);
345     resultWriter.open();
346 
347     size_t entryCount = alnDbr.getSize();
348     if (Parameters::isEqualDbtype(queryDbType, Parameters::DBTYPE_NUCLEOTIDES)) {
349         entryCount = maxContigKey + 1;
350     }
351     Debug::Progress progress(entryCount);
352 
353 #pragma omp parallel num_threads(localThreads)
354     {
355         unsigned int thread_idx = 0;
356 #ifdef OPENMP
357         thread_idx = static_cast<unsigned int>(omp_get_thread_num());
358 #endif
359         char buffer[1024 + 32768*4];
360 
361         std::string ss;
362         ss.reserve(1024);
363 
364         std::vector<Matcher::result_t> results;
365         std::vector<Matcher::result_t> tmp;
366         results.reserve(300);
367         tmp.reserve(300);
368 
369         std::string newBacktrace;
370         newBacktrace.reserve(300);
371 
372 #pragma omp for schedule(dynamic, 10)
373         for (size_t i = 0; i < entryCount; ++i) {
374             progress.updateProgress();
375             unsigned int queryKey=UINT_MAX;
376             unsigned int qLen = UINT_MAX;
377 
378             if (Parameters::isEqualDbtype(queryDbType, Parameters::DBTYPE_NUCLEOTIDES)) {
379                 queryKey = i;
380                 if (contigExists[i] == 0) {
381                     continue;
382                 }
383                 if (qSourceDbr != NULL) {
384                     size_t queryId = qSourceDbr->sequenceReader->getId(queryKey);
385                     qLen = qSourceDbr->sequenceReader->getSeqLen(queryId);
386                 }
387                 unsigned int *orfKeys = &contigLookup[contigOffsets[i]];
388                 size_t orfCount = contigOffsets[i + 1] - contigOffsets[i];
389                 for (unsigned int j = 0; j < orfCount; ++j) {
390                     unsigned int orfKey = orfKeys[j];
391                     size_t orfId = alnDbr.getId(orfKey);
392                     // this is needed when alnDbr does not contain all identifier of the queryDB
393                     if(orfId==UINT_MAX){
394                         continue;
395                     }
396                     char *data = alnDbr.getData(orfId, thread_idx);
397                     size_t queryId = qOrfDbr.sequenceReader->getId(orfKey);
398                     char *header = qOrfDbr.sequenceReader->getData(queryId, thread_idx);
399                     Orf::SequenceLocation qloc = Orf::parseOrfHeader(header);
400                     if(qloc.id == UINT_MAX){
401                         updateOffset(data, results, NULL, *tOrfDbr, (isNuclNuclSearch||isTransNucTransNucSearch), isNuclNuclSearch, thread_idx);
402                     }else{
403                         updateOffset(data, results, &qloc, *tOrfDbr, (isNuclNuclSearch||isTransNucTransNucSearch), isNuclNuclSearch, thread_idx);
404                     }
405                     // do not merge entries
406                     if(par.mergeQuery == false){
407                         for(size_t i = 0; i < results.size(); i++) {
408                             Matcher::result_t &res = results[i];
409                             bool hasBacktrace = (res.backtrace.size() > 0);
410                             if (isTransNuclAln == true && isNuclNuclSearch == false && isTransNucTransNucSearch == true && hasBacktrace) {
411                                 newBacktrace.reserve(res.backtrace.length() * 3);
412                                 Matcher::result_t::protein2nucl(res.backtrace, newBacktrace);
413                                 res.backtrace = newBacktrace;
414                                 newBacktrace.clear();
415                             }
416                             size_t len = Matcher::resultToBuffer(buffer, res, hasBacktrace, false, true);
417                             ss.append(buffer, len);
418                         }
419                         resultWriter.writeData(ss.c_str(), ss.length(), queryKey, thread_idx);
420                         results.clear();
421                         ss.clear();
422                         tmp.clear();
423                     }
424                 }
425             } else if (Parameters::isEqualDbtype(targetDbType, Parameters::DBTYPE_NUCLEOTIDES)) {
426                 queryKey = alnDbr.getDbKey(i);
427                 if (qSourceDbr != NULL) {
428                     size_t queryId = qSourceDbr->sequenceReader->getId(queryKey);
429                     qLen = qSourceDbr->sequenceReader->getSeqLen(queryId);
430                 }
431                 char *data = alnDbr.getData(i, thread_idx);
432                 updateOffset(data, results, NULL, *tOrfDbr, true, isNuclNuclSearch, thread_idx);
433             }
434             if(par.mergeQuery == true){
435                 updateLengths(results, qLen, tSourceDbr);
436                 if(par.chainAlignment == false){
437                     std::stable_sort(results.begin(), results.end(), Matcher::compareHits);
438                     for(size_t i = 0; i < results.size(); i++){
439                         Matcher::result_t &res = results[i];
440                         bool hasBacktrace = (res.backtrace.size() > 0);
441                         if (isTransNuclAln == true && isNuclNuclSearch == false && isTransNucTransNucSearch == true && hasBacktrace) {
442                             newBacktrace.reserve(res.backtrace.length() * 3);
443                             Matcher::result_t::protein2nucl(res.backtrace, newBacktrace);
444                             res.backtrace = newBacktrace;
445                             newBacktrace.clear();
446                         }
447                         size_t len = Matcher::resultToBuffer(buffer, res, hasBacktrace, false, true);
448                         ss.append(buffer, len);
449                     }
450                     resultWriter.writeData(ss.c_str(), ss.length(), queryKey, thread_idx);
451                 } else if(par.chainAlignment == true){
452                     chainAlignmentHits(results, tmp);
453                     for(size_t i = 0; i < tmp.size(); i++){
454                         Matcher::result_t &res = tmp[i];
455                         bool hasBacktrace = (res.backtrace.size() > 0);
456                         if (isTransNuclAln == true && isNuclNuclSearch == false && isTransNucTransNucSearch == true && hasBacktrace) {
457                             newBacktrace.reserve(res.backtrace.length() * 3);
458                             Matcher::result_t::protein2nucl(res.backtrace, newBacktrace);
459                             res.backtrace = newBacktrace;
460                             newBacktrace.clear();
461                         }
462                         size_t len = Matcher::resultToBuffer(buffer, res, hasBacktrace, false, true);
463                         ss.append(buffer, len);
464                     }
465                     resultWriter.writeData(ss.c_str(), ss.length(), queryKey, thread_idx);
466                 }
467                 ss.clear();
468                 results.clear();
469                 tmp.clear();
470             }
471         }
472     }
473     Debug(Debug::INFO) << "\n";
474     resultWriter.close();
475 
476     if (contigLookup != NULL) {
477         delete[] contigLookup;
478     }
479 
480     if (contigOffsets != NULL) {
481         delete[] contigOffsets;
482     }
483 
484     if (contigExists != NULL) {
485         delete[] contigExists;
486     }
487 
488     if(isSameOrfDB == false){
489         delete tOrfDbr;
490     }
491     if(tSourceDbr != NULL){
492         if(isSameSrcDB==false){
493             delete tSourceDbr;
494         }
495     }
496 
497     if(qSourceDbr != NULL){
498         delete qSourceDbr;
499     }
500     alnDbr.close();
501 
502     return EXIT_SUCCESS;
503 }
504