/** Find an equivalent region of the two specified paths, starting the * alignment at pivot1 of path1 and pivot2 of path2. * @param[out] orientation the orientation of the alignment * @return the consensus sequence */ static ContigPath align(const Lengths& lengths, const ContigPath& p1, const ContigPath& p2, ContigPath::const_iterator pivot1, ContigPath::const_iterator pivot2, dir_type& orientation) { assert(*pivot1 == *pivot2); ContigPath::const_reverse_iterator rit1 = ContigPath::const_reverse_iterator(pivot1+1), rit2 = ContigPath::const_reverse_iterator(pivot2+1); ContigPath alignmentr(p1.rend() - rit1 + p2.rend() - rit2); ContigPath::iterator rout = alignmentr.begin(); dir_type alignedr = align(lengths, rit1, p1.rend(), rit2, p2.rend(), rout); alignmentr.erase(rout, alignmentr.end()); ContigPath::const_iterator it1 = pivot1, it2 = pivot2; ContigPath alignmentf(p1.end() - it1 + p2.end() - it2); ContigPath::iterator fout = alignmentf.begin(); dir_type alignedf = align(lengths, it1, p1.end(), it2, p2.end(), fout); alignmentf.erase(fout, alignmentf.end()); ContigPath consensus; if (alignedr != DIR_X && alignedf != DIR_X) { // Found an alignment. assert(!alignmentf.empty()); assert(!alignmentr.empty()); consensus.reserve(alignmentr.size()-1 + alignmentf.size()); consensus.assign(alignmentr.rbegin(), alignmentr.rend()-1); consensus.insert(consensus.end(), alignmentf.begin(), alignmentf.end()); // Determine the orientation of the alignment. unsigned dirs = alignedr << 2 | alignedf; static const dir_type DIRS[16] = { DIR_X, // 0000 XX impossible DIR_X, // 0001 XF impossible DIR_X, // 0010 XR impossible DIR_X, // 0011 XB impossible DIR_X, // 0100 FX impossible DIR_B, // 0101 FF u is subsumed in v DIR_R, // 0110 FR v->u DIR_R, // 0111 FB v->u DIR_X, // 1000 RX impossible DIR_F, // 1001 RF u->v DIR_B, // 1010 RR v is subsumed in u DIR_F, // 1011 RB u->v DIR_X, // 1100 BX impossible DIR_F, // 1101 BF u->v DIR_R, // 1110 BR v->u DIR_B, // 1111 BB u and v are equal }; assert(dirs < 16); orientation = DIRS[dirs]; assert(orientation != DIR_X); } return consensus; }
/** Return an ambiguous path that agrees with all the given paths. */ static ContigPath constructAmbiguousPath(const Graph &g, const ContigNode& origin, const ContigPaths& paths) { assert(!paths.empty()); // Find the size of the smallest path. const ContigPath& firstSol = paths.front(); size_t min_len = firstSol.size(); for (ContigPaths::const_iterator it = paths.begin() + 1; it != paths.end(); ++it) min_len = min(min_len, it->size()); // Find the longest prefix. ContigPath vppath; size_t longestPrefix; bool commonPrefix = true; for (longestPrefix = 0; longestPrefix < min_len; longestPrefix++) { const ContigNode& common_path_node = firstSol[longestPrefix]; for (ContigPaths::const_iterator solIter = paths.begin(); solIter != paths.end(); ++solIter) { const ContigNode& pathnode = (*solIter)[longestPrefix]; if (pathnode != common_path_node) { // Found the longest prefix. commonPrefix = false; break; } } if (!commonPrefix) break; vppath.push_back(common_path_node); } // Find the longest suffix. ContigPath vspath; size_t longestSuffix; bool commonSuffix = true; for (longestSuffix = 0; longestSuffix < min_len-longestPrefix; longestSuffix++) { const ContigNode& common_path_node = firstSol[firstSol.size()-longestSuffix-1]; for (ContigPaths::const_iterator solIter = paths.begin(); solIter != paths.end(); ++solIter) { const ContigNode& pathnode = (*solIter)[solIter->size()-longestSuffix-1]; if (pathnode != common_path_node) { // Found the longest suffix. commonSuffix = false; break; } } if (!commonSuffix) break; vspath.push_back(common_path_node); } ContigPath out; out.reserve(vppath.size() + 1 + vspath.size()); out.insert(out.end(), vppath.begin(), vppath.end()); if (longestSuffix > 0) { const ContigPath& longestPath( *max_element(paths.begin(), paths.end(), ComparePathLength(g, origin))); unsigned length = calculatePathLength(g, origin, longestPath, longestPrefix, longestSuffix); // Account for the overlap on the right. int dist = length + getDistance(g, longestSuffix == longestPath.size() ? origin : *(longestPath.rbegin() + longestSuffix), *(longestPath.rbegin() + longestSuffix - 1)); // Add k-1 because it is the convention. int numN = dist + opt::k - 1; assert(numN > 0); out.push_back(ContigNode(numN, 'N')); out.insert(out.end(), vspath.rbegin(), vspath.rend()); } return out; }