/** Attempt to merge the paths specified in mergeQ with path. * @return the number of paths merged */ static unsigned mergePaths(const Lengths& lengths, ContigPath& path, deque<ContigNode>& mergeQ, set<ContigNode>& seen, const ContigPathMap& paths) { unsigned merged = 0; deque<ContigNode> invalid; for (ContigNode pivot; !mergeQ.empty(); mergeQ.pop_front()) { pivot = mergeQ.front(); ContigPathMap::const_iterator path2It = paths.find(pivot.contigIndex()); if (path2It == paths.end()) continue; ContigPath path2 = path2It->second; if (pivot.sense()) reverseComplement(path2.begin(), path2.end()); ContigPath consensus = align(lengths, path, path2, pivot); if (consensus.empty()) { invalid.push_back(pivot); continue; } appendToMergeQ(mergeQ, seen, path2); path.swap(consensus); if (gDebugPrint) #pragma omp critical(cout) cout << get(g_contigNames, pivot) << '\t' << path2 << '\n' << '\t' << path << '\n'; merged++; } mergeQ.swap(invalid); return merged; }
static void writeEstimate(ostream& out, const ContigNode& id0, const ContigNode& id1, unsigned len0, unsigned len1, const Pairs& pairs, const PMF& pmf) { if (pairs.size() < opt::npairs) return; DistanceEst est; est.distance = estimateDistance(len0, len1, pairs, pmf, est.numPairs); est.stdDev = pmf.getSampleStdDev(est.numPairs); std::pair<ContigNode, ContigNode> e(id0, id1 ^ id0.sense()); if (est.numPairs >= opt::npairs) { if (opt::format == DOT) { #pragma omp critical(out) out << get(g_contigNames, e) << " [" << est << "]\n"; } else out << ' ' << get(g_contigNames, id1) << ',' << est; } else if (opt::verbose > 1) { #pragma omp critical(cerr) cerr << "warning: " << get(g_contigNames, e) << " [d=" << est.distance << "] " << est.numPairs << " of " << pairs.size() << " pairs fit the expected distribution\n"; } }
/** Return a path, complemented if necessary. */ static ContigPath getPath(const Paths& paths, const ContigNode& u) { if (isPath(u)) { unsigned i = u.id() - Vertex::s_offset; return u.sense() ? reverseComplement(paths[i]) : paths[i]; } else return ContigPath(1, u); }
/** Return the specified path. */ static ContigPath getPath(const ContigPathMap& paths, ContigNode u) { ContigPathMap::const_iterator it = paths.find(u.contigIndex()); assert(it != paths.end()); ContigPath path = it->second; if (u.sense()) reverseComplement(path.begin(), path.end()); return path; }
/** Return the sequence of the specified contig node. The sequence * may be ambiguous or reverse complemented. */ static Sequence sequence(const Contigs& contigs, const ContigNode& id) { if (id.ambiguous()) { string s(id.ambiguousSequence()); if (s.length() < opt::k) transform(s.begin(), s.end(), s.begin(), ::tolower); return string(opt::k - 1, 'N') + s; } else { const Sequence& seq = contigs[id.id()].seq; return id.sense() ? reverseComplement(seq) : seq; } }
/** Return the sequence of the specified contig node. The sequence * may be ambiguous or reverse complemented. */ static const Sequence getSequence(ContigNode id) { if (id.ambiguous()) { string s(id.ambiguousSequence()); if (s.length() < opt::k) transform(s.begin(), s.end(), s.begin(), ::tolower); return string(opt::k - 1, 'N') + s; } else { string seq(g_contigs[id.id()]); return id.sense() ? reverseComplement(seq) : seq; } }
/** Add the overlaps of vseq to the graph. */ static void addOverlapsSA(Graph& g, const SuffixArray& sa, ContigNode v, const string& vseq) { assert(!vseq.empty()); set<ContigNode> seen; typedef SuffixArray::const_iterator It; for (string q(vseq, 0, vseq.size() - 1); q.size() >= opt::minOverlap; chop(q)) { pair<It, It> range = sa.equal_range(q); for (It it = range.first; it != range.second; ++it) { ContigNode u(it->second); if (opt::ss && u.sense() != v.sense()) continue; if (seen.insert(u).second) { // Add the longest overlap between two vertices. unsigned overlap = it->first.size(); add_edge(u, v, -overlap, static_cast<DG&>(g)); } } } }
/** Return the sequence of the specified contig. */ static string sequence(const ContigNode& id) { const string& seq = g_contigs[id.id()]; return id.sense() ? reverseComplement(seq) : seq; }
/** Identify paths subsumed by the specified path. * @param overlaps [out] paths that are found to overlap * @return the ID of the subsuming path */ static ContigID identifySubsumedPaths(const Lengths& lengths, ContigPathMap::const_iterator path1It, ContigPathMap& paths, set<ContigID>& out, set<ContigID>& overlaps) { ostringstream vout; out.clear(); ContigID id(path1It->first); const ContigPath& path = path1It->second; if (gDebugPrint) vout << get(g_contigNames, ContigNode(id, false)) << '\t' << path << '\n'; for (ContigPath::const_iterator it = path.begin(); it != path.end(); ++it) { ContigNode pivot = *it; if (pivot.ambiguous() || pivot.id() == id) continue; ContigPathMap::iterator path2It = paths.find(pivot.contigIndex()); if (path2It == paths.end()) continue; ContigPath path2 = path2It->second; if (pivot.sense()) reverseComplement(path2.begin(), path2.end()); ContigPath consensus = align(lengths, path, path2, pivot); if (consensus.empty()) continue; if (equalIgnoreAmbiguos(consensus, path)) { if (gDebugPrint) vout << get(g_contigNames, pivot) << '\t' << path2 << '\n'; out.insert(path2It->first); } else if (equalIgnoreAmbiguos(consensus, path2)) { // This path is larger. Use it as the seed. return identifySubsumedPaths(lengths, path2It, paths, out, overlaps); } else if (isCycle(lengths, consensus)) { // The consensus path is a cycle. bool isCyclePath1 = isCycle(lengths, path); bool isCyclePath2 = isCycle(lengths, path2); if (!isCyclePath1 && !isCyclePath2) { // Neither path is a cycle. if (gDebugPrint) vout << get(g_contigNames, pivot) << '\t' << path2 << '\n' << "ignored\t" << consensus << '\n'; overlaps.insert(id); overlaps.insert(path2It->first); } else { // At least one path is a cycle. if (gDebugPrint) vout << get(g_contigNames, pivot) << '\t' << path2 << '\n' << "cycle\t" << consensus << '\n'; if (isCyclePath1 && isCyclePath2) out.insert(path2It->first); else if (!isCyclePath1) overlaps.insert(id); else if (!isCyclePath2) overlaps.insert(path2It->first); } } else { if (gDebugPrint) vout << get(g_contigNames, pivot) << '\t' << path2 << '\n' << "ignored\t" << consensus << '\n'; overlaps.insert(id); overlaps.insert(path2It->first); } } cout << vout.str(); return id; }