diff --git a/src/multipath_alignment_graph.cpp b/src/multipath_alignment_graph.cpp index 6af414160c6..02cd7e285a7 100644 --- a/src/multipath_alignment_graph.cpp +++ b/src/multipath_alignment_graph.cpp @@ -2289,7 +2289,7 @@ namespace vg { // Align the tails, not collecting a set of source subpaths. // TODO: factor of 1/2 is arbitray, but i do think it should be fewer than the max auto tail_alignments = align_tails(alignment, align_graph, aligner, max(1, max_alt_alns / 2), - dynamic_alt_alns, max_gap, pessimistic_tail_gap_multiplier, max_alt_alns, nullptr); + dynamic_alt_alns, max_gap, pessimistic_tail_gap_multiplier, max_alt_alns, std::numeric_limits::max(), nullptr); for (bool handling_right_tail : {false, true}) { @@ -4225,8 +4225,9 @@ namespace vg { void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGraph& align_graph, const GSSWAligner* aligner, bool score_anchors_as_matches, size_t max_alt_alns, bool dynamic_alt_alns, size_t max_gap, - double pessimistic_tail_gap_multiplier, bool simplify_topologies, size_t unmergeable_len, - size_t band_padding, multipath_alignment_t& multipath_aln_out, SnarlManager* cutting_snarls, + double pessimistic_tail_gap_multiplier, size_t max_tail_length, bool simplify_topologies, + size_t unmergeable_len, size_t band_padding, + multipath_alignment_t& multipath_aln_out, SnarlManager* cutting_snarls, SnarlDistanceIndex* dist_index, const function(id_t)>* project, bool allow_negative_scores, unordered_map* left_align_strand) { @@ -4242,6 +4243,7 @@ void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGrap dynamic_alt_alns, max_gap, pessimistic_tail_gap_multiplier, + max_tail_length, simplify_topologies, unmergeable_len, constant_padding, @@ -5182,7 +5184,8 @@ void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGrap void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGraph& align_graph, const GSSWAligner* aligner, bool score_anchors_as_matches, size_t max_alt_alns, bool dynamic_alt_alns, size_t max_gap, - double pessimistic_tail_gap_multiplier, bool simplify_topologies, size_t unmergeable_len, + double pessimistic_tail_gap_multiplier, size_t max_tail_length, + bool simplify_topologies, size_t unmergeable_len, function band_padding_function, multipath_alignment_t& multipath_aln_out, SnarlManager* cutting_snarls, SnarlDistanceIndex* dist_index, const function(id_t)>* project, @@ -5448,7 +5451,7 @@ void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGrap // Actually align the tails auto tail_alignments = align_tails(alignment, align_graph, aligner, max_alt_alns, dynamic_alt_alns, - max_gap, pessimistic_tail_gap_multiplier, 0, &sources); + max_gap, pessimistic_tail_gap_multiplier, 0, max_tail_length, &sources); // TODO: merge and simplify the tail alignments? rescoring would be kind of a pain... @@ -5992,7 +5995,7 @@ void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGrap unordered_map>> MultipathAlignmentGraph::align_tails(const Alignment& alignment, const HandleGraph& align_graph, const GSSWAligner* aligner, size_t max_alt_alns, bool dynamic_alt_alns, size_t max_gap, double pessimistic_tail_gap_multiplier, - size_t min_paths, unordered_set* sources) { + size_t min_paths, size_t max_tail_length, unordered_set* sources) { #ifdef debug_multipath_alignment cerr << "doing tail alignments to:" << endl; @@ -6058,17 +6061,19 @@ void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGrap } int64_t target_length = tail_length + gap; - - pos_t end_pos = final_position(path_node.path); bdsg::HashGraph tail_graph; - unordered_map tail_trans = algorithms::extract_extending_graph(&align_graph, - &tail_graph, - target_length, - end_pos, - false, // search forward - false); // no need to preserve cycles (in a DAG) + unordered_map tail_trans; + if (tail_length <= max_tail_length || dynamic_alt_alns) { + // We need to pull out the tail graph + tail_trans = algorithms::extract_extending_graph(&align_graph, + &tail_graph, + target_length, + end_pos, + false, // search forward + false); // no need to preserve cycles (in a DAG) + } size_t num_alt_alns; if (dynamic_alt_alns) { @@ -6081,33 +6086,41 @@ void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGrap else { num_alt_alns = max_alt_alns; } + + if (num_alt_alns == 0) { + // Don't do any alignments + continue; + } + + // Otherwise we need an alignment to fill. + // get the sequence remaining in the right tail + Alignment right_tail_sequence; + right_tail_sequence.set_sequence(alignment.sequence().substr(path_node.end - alignment.sequence().begin(), + alignment.sequence().end() - path_node.end)); + if (!alignment.quality().empty()) { + right_tail_sequence.set_quality(alignment.quality().substr(path_node.end - alignment.sequence().begin(), + alignment.sequence().end() - path_node.end)); + } + + // And the place to put it + auto& alt_alignments = right_alignments[j]; - if (num_alt_alns > 0) { - - // get the sequence remaining in the right tail - Alignment right_tail_sequence; - right_tail_sequence.set_sequence(alignment.sequence().substr(path_node.end - alignment.sequence().begin(), - alignment.sequence().end() - path_node.end)); - if (!alignment.quality().empty()) { - right_tail_sequence.set_quality(alignment.quality().substr(path_node.end - alignment.sequence().begin(), - alignment.sequence().end() - path_node.end)); - } - #ifdef debug_multipath_alignment - cerr << "making " << num_alt_alns << " alignments of sequence: " << right_tail_sequence.sequence() << endl << "to right tail graph" << endl; - tail_graph.for_each_handle([&](const handle_t& handle) { - cerr << tail_graph.get_id(handle) << " " << tail_graph.get_sequence(handle) << endl; - tail_graph.follow_edges(handle, true, [&](const handle_t& prev) { - cerr << "\t" << tail_graph.get_id(prev) << " <-" << endl; - }); - tail_graph.follow_edges(handle, false, [&](const handle_t& next) { - cerr << "\t-> " << tail_graph.get_id(next) << endl; - }); + cerr << "making " << num_alt_alns << " alignments of sequence: " << right_tail_sequence.sequence() << endl << "to right tail graph" << endl; + tail_graph.for_each_handle([&](const handle_t& handle) { + cerr << tail_graph.get_id(handle) << " " << tail_graph.get_sequence(handle) << endl; + tail_graph.follow_edges(handle, true, [&](const handle_t& prev) { + cerr << "\t" << tail_graph.get_id(prev) << " <-" << endl; }); + tail_graph.follow_edges(handle, false, [&](const handle_t& next) { + cerr << "\t-> " << tail_graph.get_id(next) << endl; + }); + }); #endif - + + if (tail_length <= max_tail_length) { // align against the graph - auto& alt_alignments = right_alignments[j]; + if (num_alt_alns == 1) { #ifdef debug_multipath_alignment cerr << "align right with dozeu with gap " << gap << endl; @@ -6154,6 +6167,20 @@ void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGrap cerr << i << ": " << pb2json(alt_alignments[i]) << endl; } #endif + } else { + // Tail is too long. Just make a softclip directly in the base graph ID space. + // TODO: What if we just don't produce this? Do we get softclips for free? +#ifdef debug_multipath_alignment + cerr << "softclip long right" << endl; +#endif + alt_alignments.emplace_back(std::move(right_tail_sequence)); + Mapping* m = alt_alignments.back().mutable_path()->add_mapping(); + m->mutable_position()->set_node_id(id(end_pos)); + m->mutable_position()->set_is_reverse(is_rev(end_pos)); + m->mutable_position()->set_offset(offset(end_pos)); + Edit* e = m->add_edit(); + e->set_to_length(alt_alignments.back().sequence().size()); + e->set_sequence(alt_alignments.back().sequence()); } } } @@ -6185,14 +6212,17 @@ void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGrap pos_t begin_pos = initial_position(path_node.path); - bdsg::HashGraph tail_graph; - unordered_map tail_trans = algorithms::extract_extending_graph(&align_graph, - &tail_graph, - target_length, - begin_pos, - true, // search backward - false); // no need to preserve cycles (in a DAG) + unordered_map tail_trans; + if (tail_length <= max_tail_length || dynamic_alt_alns) { + // We need to pull out the tail graph + tail_trans = algorithms::extract_extending_graph(&align_graph, + &tail_graph, + target_length, + begin_pos, + true, // search backward + false); // no need to preserve cycles (in a DAG) + } size_t num_alt_alns; if (dynamic_alt_alns) { @@ -6205,30 +6235,39 @@ void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGrap else { num_alt_alns = max_alt_alns; } - - if (num_alt_alns > 0) { - - Alignment left_tail_sequence; - left_tail_sequence.set_sequence(alignment.sequence().substr(0, path_node.begin - alignment.sequence().begin())); - if (!alignment.quality().empty()) { - left_tail_sequence.set_quality(alignment.quality().substr(0, path_node.begin - alignment.sequence().begin())); - } + + if (num_alt_alns == 0) { + // Don't do any alignments + continue; + } + + // Otherwise we need an alignment to fill. + // get the sequence remaining in the left tail + Alignment left_tail_sequence; + left_tail_sequence.set_sequence(alignment.sequence().substr(0, path_node.begin - alignment.sequence().begin())); + if (!alignment.quality().empty()) { + left_tail_sequence.set_quality(alignment.quality().substr(0, path_node.begin - alignment.sequence().begin())); + } + + // And the place to put it + auto& alt_alignments = left_alignments[j]; #ifdef debug_multipath_alignment - cerr << "making " << num_alt_alns << " alignments of sequence: " << left_tail_sequence.sequence() << endl << "to left tail graph" << endl; - tail_graph.for_each_handle([&](const handle_t& handle) { - cerr << tail_graph.get_id(handle) << " " << tail_graph.get_sequence(handle) << endl; - tail_graph.follow_edges(handle, false, [&](const handle_t& next) { - cerr << "\t-> " << tail_graph.get_id(next) << endl; - }); - tail_graph.follow_edges(handle, true, [&](const handle_t& prev) { - cerr << "\t" << tail_graph.get_id(prev) << " <-" << endl; - }); + cerr << "making " << num_alt_alns << " alignments of sequence: " << left_tail_sequence.sequence() << endl << "to left tail graph" << endl; + tail_graph.for_each_handle([&](const handle_t& handle) { + cerr << tail_graph.get_id(handle) << " " << tail_graph.get_sequence(handle) << endl; + tail_graph.follow_edges(handle, false, [&](const handle_t& next) { + cerr << "\t-> " << tail_graph.get_id(next) << endl; }); + tail_graph.follow_edges(handle, true, [&](const handle_t& prev) { + cerr << "\t" << tail_graph.get_id(prev) << " <-" << endl; + }); + }); #endif + if (tail_length <= max_tail_length) { // align against the graph - auto& alt_alignments = left_alignments[j]; + if (num_alt_alns == 1) { #ifdef debug_multipath_alignment cerr << "align left with dozeu using gap " << gap << endl; @@ -6273,6 +6312,20 @@ void MultipathAlignmentGraph::align(const Alignment& alignment, const HandleGrap cerr << i << ": " << pb2json(alt_alignments[i]) << endl; } #endif + } else { + // Tail is too long. Just make a softclip directly in the base graph ID space. + // TODO: What if we just don't produce this? Do we get softclips for free? +#ifdef debug_multipath_alignment + cerr << "softclip long left" << endl; +#endif + alt_alignments.emplace_back(std::move(left_tail_sequence)); + Mapping* m = alt_alignments.back().mutable_path()->add_mapping(); + m->mutable_position()->set_node_id(id(begin_pos)); + m->mutable_position()->set_is_reverse(is_rev(begin_pos)); + m->mutable_position()->set_offset(offset(begin_pos)); + Edit* e = m->add_edit(); + e->set_to_length(alt_alignments.back().sequence().size()); + e->set_sequence(alt_alignments.back().sequence()); } } } diff --git a/src/multipath_alignment_graph.hpp b/src/multipath_alignment_graph.hpp index 752c9f56cd0..e687fd43037 100644 --- a/src/multipath_alignment_graph.hpp +++ b/src/multipath_alignment_graph.hpp @@ -194,10 +194,11 @@ namespace vg { /// order, even if this MultipathAlignmentGraph is. You MUST sort it /// with topologically_order_subpaths() before trying to run DP on it. void align(const Alignment& alignment, const HandleGraph& align_graph, const GSSWAligner* aligner, bool score_anchors_as_matches, - size_t max_alt_alns, bool dynamic_alt_alns, size_t max_gap, double pessimistic_tail_gap_multiplier, bool simplify_topologies, - size_t unmergeable_len, size_t band_padding, multipath_alignment_t& multipath_aln_out, SnarlManager* cutting_snarls = nullptr, - SnarlDistanceIndex* dist_index = nullptr, const function(id_t)>* project = nullptr, - bool allow_negative_scores = false, unordered_map* left_align_strand = nullptr); + size_t max_alt_alns, bool dynamic_alt_alns, size_t max_gap, double pessimistic_tail_gap_multiplier, size_t max_tail_length, + bool simplify_topologies, size_t unmergeable_len, size_t band_padding, multipath_alignment_t& multipath_aln_out, + SnarlManager* cutting_snarls = nullptr, SnarlDistanceIndex* dist_index = nullptr, + const function(id_t)>* project = nullptr, bool allow_negative_scores = false, + unordered_map* left_align_strand = nullptr); /// Do intervening and tail alignments between the anchoring paths and /// store the result in a multipath_alignment_t. Reachability edges must @@ -212,8 +213,8 @@ namespace vg { /// order, even if this MultipathAlignmentGraph is. You MUST sort it /// with topologically_order_subpaths() before trying to run DP on it. void align(const Alignment& alignment, const HandleGraph& align_graph, const GSSWAligner* aligner, bool score_anchors_as_matches, - size_t max_alt_alns, bool dynamic_alt_alns, size_t max_gap, double pessimistic_tail_gap_multiplier, bool simplify_topologies, - size_t unmergeable_len, function band_padding_function, + size_t max_alt_alns, bool dynamic_alt_alns, size_t max_gap, double pessimistic_tail_gap_multiplier, size_t max_tail_length, + bool simplify_topologies, size_t unmergeable_len, function band_padding_function, multipath_alignment_t& multipath_aln_out, SnarlManager* cutting_snarls = nullptr, SnarlDistanceIndex* dist_index = nullptr, const function(id_t)>* project = nullptr, bool allow_negative_scores = false, unordered_map* left_align_strand = nullptr); @@ -312,12 +313,16 @@ namespace vg { /// Alignments of the tail off of that subpath. Also computes the /// source subpaths and adds their numbers to the given set if not /// null. + /// + /// If a tail is longer than max_tail_length, produces an alignment + /// softclipping it. + /// /// If dynamic alignment count is also selected, can indicate a minimum number /// of paths that must be in the extending graph in order to do an alignment unordered_map>> align_tails(const Alignment& alignment, const HandleGraph& align_graph, const GSSWAligner* aligner, size_t max_alt_alns, bool dynamic_alt_alns, size_t max_gap, double pessimistic_tail_gap_multiplier, - size_t min_paths, unordered_set* sources = nullptr); + size_t min_paths, size_t max_tail_length, unordered_set* sources = nullptr); /// Removes alignments that follow the same path through the graph, retaining only the /// highest scoring ones. If deduplicating leftward, then also removes paths that take a diff --git a/src/multipath_mapper.cpp b/src/multipath_mapper.cpp index 55f765f3fbc..ccf1a9e8246 100644 --- a/src/multipath_mapper.cpp +++ b/src/multipath_mapper.cpp @@ -6256,9 +6256,9 @@ namespace vg { // do the connecting alignments and fill out the multipath_alignment_t object multi_aln_graph.align(alignment, *align_dag, aligner, true, num_alt_alns, dynamic_max_alt_alns, max_alignment_gap, - use_pessimistic_tail_alignment ? pessimistic_gap_multiplier : 0.0, simplify_topologies, - max_tail_merge_supress_length, choose_band_padding, multipath_aln_out, snarl_manager, - distance_index, &translator); + use_pessimistic_tail_alignment ? pessimistic_gap_multiplier : 0.0, std::numeric_limits::max(), + simplify_topologies, max_tail_merge_supress_length, choose_band_padding, multipath_aln_out, + snarl_manager, distance_index, &translator); // Note that we do NOT topologically order the multipath_alignment_t. The // caller has to do that, after it is finished breaking it up into @@ -6313,8 +6313,8 @@ namespace vg { // do the connecting alignments and fill out the multipath_alignment_t object multi_aln_graph.align(alignment, subgraph, aligner, false, num_alt_alns, dynamic_max_alt_alns, max_alignment_gap, - use_pessimistic_tail_alignment ? pessimistic_gap_multiplier : 0.0, simplify_topologies, - max_tail_merge_supress_length, choose_band_padding, multipath_aln_out); + use_pessimistic_tail_alignment ? pessimistic_gap_multiplier : 0.0, std::numeric_limits::max(), + simplify_topologies, max_tail_merge_supress_length, choose_band_padding, multipath_aln_out); for (size_t j = 0; j < multipath_aln_out.subpath_size(); j++) { translate_oriented_node_ids(*multipath_aln_out.mutable_subpath(j)->mutable_path(), translator); diff --git a/src/subcommand/surject_main.cpp b/src/subcommand/surject_main.cpp index 8121ababf47..78e397431c8 100644 --- a/src/subcommand/surject_main.cpp +++ b/src/subcommand/surject_main.cpp @@ -47,6 +47,7 @@ void help_surject(char** argv) { << " -b, --bam-output write BAM to stdout" << endl << " -s, --sam-output write SAM to stdout" << endl << " -l, --subpath-local let the multipath mapping surjection produce local (rather than global) alignments" << endl + << " -T, --max-tail-len N do not align read tails longer than N" << endl << " -P, --prune-low-cplx prune short and low complexity anchors during realignment" << endl << " -a, --max-anchors N use no more than N anchors per target path (default: 200)" << endl << " -S, --spliced interpret long deletions against paths as spliced alignments" << endl @@ -96,6 +97,7 @@ int main_surject(int argc, char** argv) { int min_splice_length = 20; size_t watchdog_timeout = 10; bool subpath_global = true; // force full length alignments in mpmap resolution + size_t max_tail_len = std::numeric_limits::max(); bool qual_adj = false; bool prune_anchors = false; size_t max_anchors = 200; @@ -114,7 +116,8 @@ int main_surject(int argc, char** argv) { {"into-path", required_argument, 0, 'p'}, {"into-paths", required_argument, 0, 'F'}, {"ref-paths", required_argument, 0, 'F'}, // Now an alias for --into-paths - {"subpath-local", required_argument, 0, 'l'}, + {"subpath-local", no_argument, 0, 'l'}, + {"max-tail-len", required_argument, 0, 'T'}, {"interleaved", no_argument, 0, 'i'}, {"multimap", no_argument, 0, 'M'}, {"gaf-input", no_argument, 0, 'G'}, @@ -137,7 +140,7 @@ int main_surject(int argc, char** argv) { }; int option_index = 0; - c = getopt_long (argc, argv, "hx:p:F:liGmcbsN:R:f:C:t:SPa:ALMVw:", + c = getopt_long (argc, argv, "hx:p:F:lT:iGmcbsN:R:f:C:t:SPa:ALMVw:", long_options, &option_index); // Detect the end of the options. @@ -163,6 +166,10 @@ int main_surject(int argc, char** argv) { subpath_global = false; break; + case 'T': + max_tail_len = parse(optarg); + break; + case 'i': interleaved = true; break; @@ -303,8 +310,9 @@ int main_surject(int argc, char** argv) { else { surjector.min_splice_length = numeric_limits::max(); } + surjector.max_tail_length = max_tail_len; surjector.annotate_with_all_path_scores = annotate_with_all_path_scores; - + // Count our threads int thread_count = vg::get_thread_count(); diff --git a/src/surjector.cpp b/src/surjector.cpp index 23589d696f2..7cf136f22f1 100644 --- a/src/surjector.cpp +++ b/src/surjector.cpp @@ -3095,6 +3095,7 @@ using namespace std; false, // dynamic alt alns numeric_limits::max(), // max gap 0.0, // pessimistic tail gap multiplier + max_tail_length, // max length of tail to align false, // simplify topologies 0, // unmergeable len 1, // band padding diff --git a/src/surjector.hpp b/src/surjector.hpp index 9df1c0a8da7..40c9b44f5a8 100644 --- a/src/surjector.hpp +++ b/src/surjector.hpp @@ -108,6 +108,9 @@ using namespace std; /// the minimum length apparent intron that we will try to repair int64_t min_splice_repair_length = 250; + + /// the maximum length of a tail that we will try to align + size_t max_tail_length = std::numeric_limits::max(); /// How big of a graph in bp should we ever try to align against for realigning surjection? size_t max_subgraph_bases = 100 * 1024; diff --git a/src/unittest/multipath_alignment_graph.cpp b/src/unittest/multipath_alignment_graph.cpp index 7d323e33675..9b08215dfd7 100644 --- a/src/unittest/multipath_alignment_graph.cpp +++ b/src/unittest/multipath_alignment_graph.cpp @@ -110,7 +110,7 @@ TEST_CASE( "MultipathAlignmentGraph::align handles tails correctly", "[multipath mpg.resect_snarls_from_paths(&snarl_manager, identity, 5); // Make it align, with alignments per gap/tail - mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, 5, out); + mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, std::numeric_limits::max(), false, 5, out); // Make sure to topologically sort the resulting alignment. TODO: Should // the MultipathAlignmentGraph guarantee this for us by construction? @@ -148,7 +148,7 @@ TEST_CASE( "MultipathAlignmentGraph::align handles tails correctly", "[multipath SECTION("Handles tails when anchors for them are not generated") { // Make it align, with alignments per gap/tail - mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, 5, out); + mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, std::numeric_limits::max(), false, 5, out); // Make sure to topologically sort the resulting alignment. TODO: Should // the MultipathAlignmentGraph guarantee this for us by construction? @@ -208,7 +208,7 @@ TEST_CASE( "MultipathAlignmentGraph::align handles tails correctly", "[multipath MultipathAlignmentGraph::create_projector(identity), 5); // Make it align, with alignments per gap/tail - mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, false, 0, 5, out); + mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, std::numeric_limits::max(), false, 0, 5, out); // Make sure to topologically sort the resulting alignment. TODO: Should // the MultipathAlignmentGraph guarantee this for us by construction? @@ -244,7 +244,7 @@ TEST_CASE( "MultipathAlignmentGraph::align handles tails correctly", "[multipath SECTION("Handles tails when anchors for them are not generated") { // Make it align, with alignments per gap/tail - mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, false, 0, 5, out); + mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, std::numeric_limits::max(), false, 0, 5, out); // Make sure to topologically sort the resulting alignment. TODO: Should // the MultipathAlignmentGraph guarantee this for us by construction? @@ -301,7 +301,7 @@ TEST_CASE( "MultipathAlignmentGraph::align handles tails correctly", "[multipath MultipathAlignmentGraph::create_projector(identity), 5); // Make it align, with alignments per gap/tail - mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, false, 0, 5, out); + mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, std::numeric_limits::max(), false, 0, 5, out); // Make sure to topologically sort the resulting alignment. TODO: Should // the MultipathAlignmentGraph guarantee this for us by construction? @@ -338,7 +338,7 @@ TEST_CASE( "MultipathAlignmentGraph::align handles tails correctly", "[multipath SECTION("Handles tails when anchors for them are not generated") { // Make it align, with alignments per gap/tail - mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, false, 0, 5, out); + mpg.align(query, vg, &aligner, true, 2, false, 100, 0.0, std::numeric_limits::max(), false, 0, 5, out); // Make sure to topologically sort the resulting alignment. TODO: Should // the MultipathAlignmentGraph guarantee this for us by construction?