Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SDSL assertion error when working with graph from vg mod -M 8 #2681

Closed
LilithElina opened this issue Mar 20, 2020 · 18 comments · Fixed by #2697
Closed

SDSL assertion error when working with graph from vg mod -M 8 #2681

LilithElina opened this issue Mar 20, 2020 · 18 comments · Fixed by #2697

Comments

@LilithElina
Copy link

1. What were you trying to do?
I updated from vg 1.19.0 to 1.22.0 and wanted to continue working with my genome graph, after I ran into problems during or after mapping reads to that graph, as posted here and here.

2. What did you want to happen?
When I tried mapping to the graph and indices I already had, I got warning that I was using an out-of-date XG format, so I decided to create new indices, like this:

vg mod -X 32 graph.vg | vg mod -M 8 - | vg sort - > graph_mod.vg
vg index -x graph_mod.xg graph_mod.vg
vg prune -k 16 -e 3 graph_mod.vg > graph_prune.vg
vg index -g graph_mod.gcsa -k 16 graph_prune.vg

3. What actually happened?
The first line already didn't work. The vg mod commands are fine, but vg sort crashes right away with the following message:

terminate called after throwing an instance of 'std::runtime_error'
  what():  [io::ProtobufIterator] tag "HashGraph" for Protobuf that should be "VG"
ERROR: Signal 6 occurred. VG has crashed. Run 'vg bugs --new' to report a bug.
Stack trace path: /tmp/vg_crash_2xOBkY/stacktrace.txt
Please include the stack trace file in your bug report!

4. If you got a line like Stack trace path: /somewhere/on/your/computer/stacktrace.txt, please copy-paste the contents of that file here:

Crash report for vg v1.22.0 "Rotella"
Stack trace (most recent call last):
#18   Object "", at 0xffffffffffffffff, in 
#17   Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x7f1798, in _start
#16   Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7fbe225f782f, in __libc_start_main
#15   Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x735074, in main
      Source "src/main.cpp", line 75, in main [0x735074]
#14   Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xcb86a7, in vg::subcommand::Subcommand::operator()(int, char**) const
    | Source "src/subcommand/subcommand.cpp", line 72, in operator()
      Source "/usr/include/c++/5/functional", line 2267, in operator() [0xcb86a7]
       2264:     {
       2265:       if (_M_empty())
       2266: 	__throw_bad_function_call();
      >2267:       return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
       2268:     }
       2269: 
       2270: #if __cpp_rtti
#13   Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xc28d18, in main_sort(int, char**)
      Source "src/subcommand/sort_main.cpp", line 209, in main_sort [0xc28d18]
#12   Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xd97d76, in vg::get_input_file(int&, int, char**, std::function<void (std::istream&)>)
      Source "src/utility.cpp", line 370, in get_input_file [0xd97d76]
#11   Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xd97a39, in vg::get_input_file(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::function<void (std::istream&)>)
    | Source "src/utility.cpp", line 416, in operator()
      Source "/usr/include/c++/5/functional", line 2267, in get_input_file [0xd97a39]
       2264:     {
       2265:       if (_M_empty())
       2266: 	__throw_bad_function_call();
      >2267:       return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
       2268:     }
       2269: 
       2270: #if __cpp_rtti
#10   Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xc29349, in main_sort(int, char**)::{lambda(std::istream&)#1}::operator()(std::istream&) const [clone .constprop.190]
      Source "src/subcommand/sort_main.cpp", line 146, in operator() [0xc29349]
#9    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xf1eefc, in vg::VG::VG(std::istream&, bool, bool)
      Source "src/vg.cpp", line 28, in VG [0xf1eefc]
#8    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xf1e8e5, in vg::VG::from_istream(std::istream&, bool, bool)
    | Source "src/vg.cpp", line 79, in for_each<vg::Graph>
      Source "/data3/genome_graphs/vg-v1.22.0/include/vg/io/stream.hpp", line 117, in from_istream [0xf1e8e5]
        114: template <typename T>
        115: void for_each(std::istream& in,
        116:               const std::function<void(T&)>& lambda) {
      > 117:     for_each(in, static_cast<const typename std::function<void(int64_t, T&)>&>([&lambda](int64_t virtual_offset, T& item) {
        118:         lambda(item);
        119:     }));
        120: }
#7    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xa2f672, in void vg::io::for_each<vg::Graph>(std::istream&, std::function<void (long, vg::Graph&)> const&)
    | Source "/data3/genome_graphs/vg-v1.22.0/include/vg/io/stream.hpp", line 108, in ProtobufIterator
    |   106:               const std::function<void(int64_t, T&)>& lambda) {
    |   107:     
    | > 108:     for(ProtobufIterator<T> it(in); it.has_current(); ++it) {
    |   109:         // For each message in the file, parse and process it with its group VO (or -1)
    |   110:         lambda(it.tell_group(), *it);
      Source "/data3/genome_graphs/vg-v1.22.0/include/vg/io/protobuf_iterator.hpp", line 124, in for_each<vg::Graph> [0xa2f672]
        121: template<typename T>
        122: ProtobufIterator<T>::ProtobufIterator(istream& in) : message_it(in) {
        123:     // Make sure to fill in our value field.
      > 124:     fill_value();
        125: }
        126: 
        127: template<typename T>
#6    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xa2f2da, in vg::io::ProtobufIterator<vg::Graph>::fill_value()
      Source "/data3/genome_graphs/vg-v1.22.0/include/vg/io/protobuf_iterator.hpp", line 213, in fill_value [0xa2f2da]
        210:             // The registry doesn't think this tag is legit for what we are parsing.
        211:             // Abort!
        212:             throw runtime_error("[io::ProtobufIterator] tag \"" + tag +
      > 213:                 "\" for Protobuf that should be \"" + Registry::get_protobuf_tag<T>() + "\"");
        214:                 
        215:             // TODO: Skip over these instead of aborting to allow for multiplexing (i.e. VG in with XG)
        216:         }
#5    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21", at 0x7fbe22e66918, in __cxa_throw
#4    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21", at 0x7fbe22e66700, in std::terminate()
#3    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21", at 0x7fbe22e666b5, in 
#2    Object "/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21", at 0x7fbe22e6884c, in __gnu_cxx::__verbose_terminate_handler()
#1    Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7fbe2260e029, in abort
#0    Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7fbe2260c428, in raise

5. What data and command can the vg dev team use to make the problem happen?
I can put the graph somewhere to download if necessary.
I also tried creating the graph again to see if that made a difference, but I made it with minimap2+seqwish and only used vg view to convert to vg format and doing that again did not resolve the issue.

6. What does running vg version say?

vg version v1.22.0 "Rotella"
Compiled with g++ (Ubuntu 5.4.0-6ubuntu1~16.04.12) 5.4.0 20160609 on Linux
Linked against libstd++ 20160609
Built by spo12@CPI-SL64001
@jeizenga
Copy link
Contributor

@adamnovak this looks like it's related to the move to HashGraph and default serialization type?

@adamnovak
Copy link
Member

Oh the problem here is that we moved to a new output format for most commands (HashGraph), but since it stores everything in a hash table it has no concept of an ordering, so sorting it doesn't make sense. vg sort still only reads the old format, and when it encounters the new format it complains that its input is the wrong format instead of converting it back to the old, ordered format and sorting it.

I think the solution here is to drop the vg sort step from the pipeline. I don't think it is necessary anymore. vg index is smart enough to process the graph elements in the right order when you give it an unordered HashGraph.

Did this pipeline come from a wiki page that we maybe need to update?

@LilithElina
Copy link
Author

LilithElina commented Mar 21, 2020

Oh, I wasn't aware of that, I should pay more attention to release notes! Thank you for your quick response.

I think I got the pipeline from the CPANG19 course @ekg gave last year.

@LilithElina
Copy link
Author

I have another problem with the same pipeline, should I open a new issue for that? Neither vg prune nor vg index can work with the graph modified with vg mod -X 32 graph.vg | vg mod -M 8. Both return the following error message:

vg: /data3/genome_graphs/vg-v1.22.0/include/sdsl/select_support_mcl.hpp:349: sdsl::select_support::size_type sdsl::select_support_mcl<t_bit_pattern, t_pattern_len>::select(sdsl::select_support::size_type) const [with unsigned char t_b = 1u; unsigned char t_pat_len = 1u; sdsl::select_support::size_type = long unsigned int]: Assertion `i > 0 and i <= m_arg_cnt' failed.
ERROR: Signal 6 occurred. VG has crashed. Run 'vg bugs --new' to report a bug.
Stack trace path: /tmp/vg_crash_HY35mt/stacktrace.txt
Please include the stack trace file in your bug report!

@LilithElina LilithElina reopened this Mar 24, 2020
@adamnovak adamnovak changed the title std::runtime_error from vg sort SDSL assertion error when working with graph from vg mod -M 8 Mar 24, 2020
@adamnovak
Copy link
Member

Hm. That shouldn't happen, as far as I know. I can't think of a way that vg index -x graph_mod.xg graph_mod.vg and vg prune -k 16 -e 3 graph_mod.vg > graph_prune.vg would both manage to do the same out-of-range SDSL select (which is what the error appears to be complaining about).

It would be useful to have the stack trace files for both commands failing, and also probably the broken graph, and the original graph.

Can anything load that broken graph? You could try vg stats -z graph_mod.vg, which is just supposed to count nodes and edges.

I do manage to get an error out of the second vg index call when vg prune prunes away the entire graph, but for an ordinary graph where that doesn't happen, the pipeline runs through for me:

vg construct -r test/small/x.fa -v test/small/x.vcf.gz >graph.vg

vg mod -X 32 graph.vg | vg mod -M 8 - > graph_mod.vg
vg index -x graph_mod.xg graph_mod.vg
vg prune -k 16 -e 3 graph_mod.vg > graph_prune.vg
vg index -g graph_mod.gcsa -k 16 graph_prune.vg

@LilithElina
Copy link
Author

The graph doesn't seem to be broken on first glance: vg stats -z graph_mod.vg gives me the following output:

nodes   1265264
edges   1644925

Running vg index -x graph_mod.xg graph_mod.vg results in this error:

vg: /data3/genome_graphs/vg-v1.22.0/include/sdsl/select_support_mcl.hpp:349: sdsl::select_support::size_type sdsl::select_support_mcl<t_bit_pattern, t_pattern_len>::select(sdsl::select_support::size_type) const [with unsigned char t_b = 1u; unsigned char t_pat_len = 1u; sdsl::select_support::size_type = long unsigned int]: Assertion `i > 0 and i <= m_arg_cnt' failed.
ERROR: Signal 6 occurred. VG has crashed. Run 'vg bugs --new' to report a bug.
Stack trace path: /tmp/vg_crash_jtjaMZ/stacktrace.txt
Please include the stack trace file in your bug report!

and this stack trace file:

Crash report for vg v1.22.0 "Rotella"
Stack trace (most recent call last):
#12   Object "", at 0xffffffffffffffff, in
#11   Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x7f1798, in _start
#10   Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7f93a16bb82f, in __libc_start_main
#9    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x735074, in main
      Source "src/main.cpp", line 75, in main [0x735074]
#8    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xcb86a7, in vg::subcommand::Subcommand::operator()(int, char**) const
    | Source "src/subcommand/subcommand.cpp", line 72, in operator()
      Source "/usr/include/c++/5/functional", line 2267, in operator() [0xcb86a7]
       2264:     {
       2265:       if (_M_empty())
       2266:    __throw_bad_function_call();
      >2267:       return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
       2268:     }
       2269:
       2270: #if __cpp_rtti
#7    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xc1d9de, in main_index(int, char**)
      Source "src/subcommand/index_main.cpp", line 551, in main_index [0xc1d9de]
#6    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xfd10b0, in vg::VGset::to_xg(xg::XG&, std::function<bool (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)> const&, std::map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, vg::Path, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, vg::Path> > >*)
      Source "src/vg_set.cpp", line 212, in to_xg [0xfd10b0]
#5    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x16aa898, in xg::XG::from_enumerators(std::function<void (std::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, long const&)> const&)> const&, std::function<void (std::function<void (long const&, bool const&, long const&, bool const&)> const&)> const&, std::function<void (std::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, long const&, bool const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool const&, bool const&)> const&)> const&, bool, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
    | Source "deps/xg/src/xg.cpp", line 882, in operator()
    | Source "deps/xg/src/xg.cpp", line 834, in operator()
      Source "/data3/genome_graphs/vg-v1.22.0/include/sdsl/select_support_mcl.hpp", line 398, in from_enumerators [0x16aa898]
        395: template<uint8_t t_b, uint8_t t_pat_len>
        396: inline auto select_support_mcl<t_b,t_pat_len>::operator()(size_type i)const -> size_type
        397: {
      > 398:     return select(i);
        399: }
        400:
        401: template<uint8_t t_b, uint8_t t_pat_len>
#4    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x833552, in sdsl::select_support_mcl<(unsigned char)1, (unsigned char)1>::select(unsigned long) const
      Source "/data3/genome_graphs/vg-v1.22.0/include/sdsl/select_support_mcl.hpp", line 349, in select [0x833552]
        346: template<uint8_t t_b, uint8_t t_pat_len>
        347: inline auto select_support_mcl<t_b,t_pat_len>::select(size_type i)const -> size_type
        348: {
      > 349:     assert(i > 0 and i <= m_arg_cnt);
        350:
        351:     i = i-1;
        352:     size_type sb_idx = i>>12;   // i/4096
#3    Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7f93a16c8c81, in __assert_fail
#2    Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7f93a16c8bd6, in
#1    Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7f93a16d2029, in abort
#0    Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7f93a16d0428, in raise

The error message from vg prune -r graph_mod.vg > graph_prune.vg is the same as before, the stack trace file is only slightly different:

Crash report for vg v1.22.0 "Rotella"
Stack trace (most recent call last):
#12   Object "", at 0xffffffffffffffff, in
#11   Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x7f1798, in _start
#10   Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7ff95080d82f, in __libc_start_main
#9    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x735074, in main
      Source "src/main.cpp", line 75, in main [0x735074]
#8    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xcb86a7, in vg::subcommand::Subcommand::operator()(int, char**) const
    | Source "src/subcommand/subcommand.cpp", line 72, in operator()
      Source "/usr/include/c++/5/functional", line 2267, in operator() [0xcb86a7]
       2264:     {
       2265:       if (_M_empty())
       2266:    __throw_bad_function_call();
      >2267:       return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...);
       2268:     }
       2269:
       2270: #if __cpp_rtti
#7    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0xc9c260, in main_prune(int, char**)
      Source "src/subcommand/prune_main.cpp", line 370, in main_prune [0xc9c260]
#6    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x16acff1, in xg::XG::from_path_handle_graph(handlegraph::PathHandleGraph const&)
      Source "deps/xg/src/xg.cpp", line 729, in from_path_handle_graph [0x16acff1]
#5    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x16aa898, in xg::XG::from_enumerators(std::function<void (std::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, long const&)> const&)> const&, std::function<void (std::function<void (long const&, bool const&, long const&, bool const&)> const&)> const&, std::function<void (std::function<void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, long const&, bool const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool const&, bool const&)> const&)> const&, bool, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
    | Source "deps/xg/src/xg.cpp", line 882, in operator()
    | Source "deps/xg/src/xg.cpp", line 834, in operator()
      Source "/data3/genome_graphs/vg-v1.22.0/include/sdsl/select_support_mcl.hpp", line 398, in from_enumerators [0x16aa898]
        395: template<uint8_t t_b, uint8_t t_pat_len>
        396: inline auto select_support_mcl<t_b,t_pat_len>::operator()(size_type i)const -> size_type
        397: {
      > 398:     return select(i);
        399: }
        400:
        401: template<uint8_t t_b, uint8_t t_pat_len>
#4    Object "/data3/genome_graphs/vg-v1.22.0/bin/vg", at 0x833552, in sdsl::select_support_mcl<(unsigned char)1, (unsigned char)1>::select(unsigned long) const
      Source "/data3/genome_graphs/vg-v1.22.0/include/sdsl/select_support_mcl.hpp", line 349, in select [0x833552]
        346: template<uint8_t t_b, uint8_t t_pat_len>
        347: inline auto select_support_mcl<t_b,t_pat_len>::select(size_type i)const -> size_type
        348: {
      > 349:     assert(i > 0 and i <= m_arg_cnt);
        350:
        351:     i = i-1;
        352:     size_type sb_idx = i>>12;   // i/4096
#3    Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7ff95081ac81, in __assert_fail
#2    Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7ff95081abd6, in
#1    Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7ff950824029, in abort
#0    Object "/lib/x86_64-linux-gnu/libc-2.23.so", at 0x7ff950822428, in raise

@adamnovak
Copy link
Member

adamnovak commented Mar 25, 2020 via email

@LilithElina
Copy link
Author

Is there anything I can do? Wothout pruning I'm running out of disk space.

The graph was generated with minimap2 and seqwish, and I converted it to vg with vg view before starting with the modifications.

@adamnovak
Copy link
Member

adamnovak commented Mar 26, 2020

It definitely needs to be pruned...

I'm not sure there's a workaround, besides cutting the xg generation out of vg prune which no longer needs it. In theory you should now be able to just use the original graph anywhere you used to need an xg file, so if it could be pruned you could bypass the flaky xg build altogether.

Is there a way you can share the graph? It would help a lot to be able to figure out exactly what it is doing to upset the xg builder.

@LilithElina
Copy link
Author

Yes, sure, I put the graph in my Google Drive. I also have online protocols for the graph creation and my tries to map reads to it.

@adamnovak
Copy link
Member

OK, I'm able to replicate the issue.

The immediate problem here is that the graph being fed to xg generation contains empty nodes (nodes with "" for a sequence). These are generally not supposed to be there, and the XG format AFAIK can't actually represent them.

It looks like they are being created because vg mod -M 8 is deleting nodes and edges but not the paths that visit them, and paths cannot exist in our new internal format without nodes. @jeizenga this seems to be a design problem/disagreement between the code that removes high-degree nodes (which doesn't know or care about paths):

void remove_high_degree_nodes(DeletableHandleGraph& g, int max_degree) {
vector<handle_t> to_remove;
g.for_each_handle([&](const handle_t& h) {
int edge_count = 0;
g.follow_edges(h, false, [&](const handle_t& ignored) {
++edge_count;
});
g.follow_edges(h, true, [&](const handle_t& ignored) {
++edge_count;
});
if (edge_count > max_degree) {
to_remove.push_back(h);
}
});
// now destroy the high degree nodes
for (auto& h : to_remove) {
g.destroy_handle(h);
}

and the semantics of destroy_handle (which doesn't destroy paths):

https://github.com/vgteam/libhandlegraph/blob/98b12c89087a5c0cee8341f80701db4d0fc53e55/src/include/handlegraph/deletable_handle_graph.hpp#L21-L27

This allows us to end up with a HashGraph that contains visits to nodes that don't exist, and because we use graph[] instead of graph.at() (maybe here?), we end up default-constructing empty nodes to visit, instead of crashing when we try to do something involving these nodes that don't exist. These empty nodes make it into xg indexing where they screw things up.

A workaround is to remove all the paths from the graph before using vg mod -M 8:

vg mod -X 32 graph.vg | vg paths -v - -d | vg mod -M 8 - > graph_mod.vg

However, obviously then there are no paths at all, even if not all paths wold have been broken by the removal of the high-degree nodes.

Another workaround would be to skip the removal of the high degree nodes altogether, and to just hope that the pruning step sufficiently reduces the complexity of the graph. vg prune is smart enough to destroy all the paths before it starts modifying the graph, and to being back the nodes needed to keep paths connected if you ask it to put the paths back in at the end.

@LilithElina
Copy link
Author

Thank you! Leaving the removal of high degree nodes out has worked, I now have the xg and the gcsa index.

@glennhickey
Copy link
Contributor

Just a quick comment on the avoid-xg workaround up in #2681 (comment): Even though we can represent empty nodes in the non-xg formats, I'm pretty sure there are several places in the code where they will lead to undefined results. Definitely want to nip these in the bud, so the new error message in xg is very helpful, and should probably be ported across implementations.

@jeizenga
Copy link
Contributor

@adamnovak I think removing a node on a path is documented as undefined behavior in libhandlegraph, since it's not really clear what the right thing to do with the path would be. I think the algorithm should probably be made path-aware if we want to keep it.

@adamnovak
Copy link
Member

It looks like actually prohibiting empty nodes in all our handle graph implementations breaks vg::algorithms::extract_extending_graph, which expects to be able to create empty nodes when you want to extract the graph that extends off of the very end of a node.

@adamnovak
Copy link
Member

adamnovak commented Mar 31, 2020 via email

@adamnovak
Copy link
Member

adamnovak commented Mar 31, 2020 via email

@jeizenga
Copy link
Contributor

Destroying the path seems sensible to me. I know @ekg has some other ideas about leaving "hidden handles" around to preserve paths when nodes have been removed. Also, I think it might be possible to rewrite the code around extract_extending_graph and extract_connecting_graph so that they wouldn't need empty nodes anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants