This is an automated email from the git hooks/post-receive script. tille pushed a commit to branch master in repository abyss.
commit fe441e45d54dba1acfdaf67dbaa227f7e2d42e5b Author: Andreas Tille <[email protected]> Date: Tue Nov 1 12:04:19 2016 +0100 Imported Upstream version 2.0.2 --- BloomDBG/bloom-dbg.cc | 5 +- ChangeLog | 5 + Common/Dictionary.h | 8 + Graph/DotIO.h | 59 +- Graph/GraphIO.h | 3 +- Graph/Makefile.am | 3 +- Graph/SAMIO.h | 1 + Graph/UndirectedGraph.h | 948 +++++++++++++++++++++++++++++++++ Konnector/DBGBloom.h | 9 + README.md | 26 +- Unittest/DBG/LoadAlgorithmTest.cpp | 1 + Unittest/Graph/DotIOTest.cpp | 115 ++++ Unittest/Graph/UndirectedGraphTest.cpp | 54 ++ Unittest/Makefile.am | 15 + configure.ac | 13 +- doc/ABYSS.1 | 2 +- doc/abyss-pe.1 | 2 +- doc/abyss-tofastq.1 | 2 +- doc/flowchart.graffle | 2 +- 19 files changed, 1250 insertions(+), 23 deletions(-) diff --git a/BloomDBG/bloom-dbg.cc b/BloomDBG/bloom-dbg.cc index 2c6a05b..9ace1d5 100644 --- a/BloomDBG/bloom-dbg.cc +++ b/BloomDBG/bloom-dbg.cc @@ -41,8 +41,9 @@ static const char USAGE_MESSAGE[] = "\n" "Basic Options:\n" "\n" -" -b --bloom-size=N Bloom filter memory size with unit suffix\n" -" 'k', 'M', or 'G' [required]\n" +" -b --bloom-size=N overall memory budget for the assembly in bytes.\n" +" Unit suffixes 'k' (kilobytes), 'M' (megabytes),\n" +" or 'G' (gigabytes) may be used. [required]\n" " --chastity discard unchaste reads [default]\n" " --no-chastity do not discard unchaste reads\n" " -g --graph=FILE write de Bruijn graph to FILE (GraphViz)\n" diff --git a/ChangeLog b/ChangeLog index 368e132..f07eade 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-10-21 Ben Vandervalk <[email protected]> + + * Release version 2.0.2 + * Fix compile errors with gcc 6 and boost 1.62 + 2016-09-14 Ben Vandervalk <[email protected]> * Release version 2.0.1 diff --git a/Common/Dictionary.h b/Common/Dictionary.h index 88f227a..f917fc4 100644 --- a/Common/Dictionary.h +++ b/Common/Dictionary.h @@ -100,6 +100,14 @@ class Dictionary return m_vec.back(); } + /** Clear dictionary contents and reset to default state. */ + void clear() + { + m_map.clear(); + m_vec.clear(); + m_locked = false; + } + private: Map m_map; Vector m_vec; diff --git a/Graph/DotIO.h b/Graph/DotIO.h index 1c8449e..af76ed4 100644 --- a/Graph/DotIO.h +++ b/Graph/DotIO.h @@ -133,15 +133,61 @@ DotWriter<Graph> dot_writer(const Graph& g) return DotWriter<Graph>(g); } +/** legal characters for an unquoted node ID */ +static const uint8_t GRAPHVIZ_ID_CHARS[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, // 000-007: + 0, 0, 0, 0, 0, 0, 0, 0, // 008-015: + 0, 0, 0, 0, 0, 0, 0, 0, // 016-023: + 0, 0, 0, 0, 0, 0, 0, 0, // 024-031: + 0, 0, 0, 0, 0, 0, 0, 0, // 032-039: !, ", #, $, %, &, ', + 0, 0, 0, 1, 0, 1, 1, 0, // 040-047: (, ), *, +, ,, -, ., /, + 1, 1, 1, 1, 1, 1, 1, 1, // 048-055: 0, 1, 2, 3, 4, 5, 6, 7, + 1, 1, 0, 0, 0, 0, 0, 0, // 056-063: 8, 9, :, ;, <, =, >, ?, + 0, 1, 1, 1, 1, 1, 1, 1, // 064-071: @, A, B, C, D, E, F, G, + 1, 1, 1, 1, 1, 1, 1, 1, // 072-079: H, I, J, K, L, M, N, O, + 1, 1, 1, 1, 1, 1, 1, 1, // 080-087: P, Q, R, S, T, U, V, W, + 1, 1, 1, 0, 0, 0, 0, 1, // 088-095: X, Y, Z, [, \, ], ^, _, + 0, 1, 1, 1, 1, 1, 1, 1, // 096-103: `, a, b, c, d, e, f, g, + 1, 1, 1, 1, 1, 1, 1, 1, // 104-111: h, i, j, k, l, m, n, o, + 1, 1, 1, 1, 1, 1, 1, 1, // 112-119: p, q, r, s, t, u, v, w, + 1, 1, 1, 0, 0, 0, 0, 0, // 120-127: x, y, z, {, |, }, ~, + 0, 0, 0, 0, 0, 0, 0, 0, // 128-135: + 0, 0, 0, 0, 0, 0, 0, 0, // 136-143: + 0, 0, 0, 0, 0, 0, 0, 0, // 144-151: + 0, 0, 0, 0, 0, 0, 0, 0, // 152-159: + 0, 0, 0, 0, 0, 0, 0, 0, // 160-167: + 0, 0, 0, 0, 0, 0, 0, 0, // 168-175: + 0, 0, 0, 0, 0, 0, 0, 0, // 176-183: + 0, 0, 0, 0, 0, 0, 0, 0, // 184-191: + 0, 0, 0, 0, 0, 0, 0, 0, // 192-199: + 0, 0, 0, 0, 0, 0, 0, 0, // 200-207: + 0, 0, 0, 0, 0, 0, 0, 0, // 208-215: + 0, 0, 0, 0, 0, 0, 0, 0, // 216-223: + 0, 0, 0, 0, 0, 0, 0, 0, // 224-231: + 0, 0, 0, 0, 0, 0, 0, 0, // 232-239: + 0, 0, 0, 0, 0, 0, 0, 0, // 240-247: + 0, 0, 0, 0, 0, 0, 0, 0 // 248-255: +}; + /** Read a string delimited by double quotes. */ static inline std::istream& read_dot_name(std::istream& in, std::string& s) { - if (in >> std::ws && in.peek() == '"') { + in >> std::ws; + if (in.peek() == '"') { + // quoted node ID in.get(); getline(in, s, '"'); - } else + } else if (GRAPHVIZ_ID_CHARS[in.peek()]) { + // unquoted node ID + std::ostringstream ss; + while (GRAPHVIZ_ID_CHARS[in.peek()]) + ss << (char)in.get(); + assert(ss.good()); + s = ss.str(); + } else { in.clear(std::ios::failbit); + } return in; } @@ -170,12 +216,17 @@ std::istream& read_dot(std::istream& in, Graph& g, BetterEP betterEP) typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor; typedef typename edge_property<Graph>::type edge_property_type; + typedef typename graph_traits<Graph>::directed_category + directed_category; + + bool isDirectedGraph = boost::detail::is_directed(directed_category()); // Add vertices if this graph is empty. bool addVertices = num_vertices(g) == 0; // Graph properties - in >> expect("digraph") >> Ignore('{'); + in >> expect(isDirectedGraph ? "digraph" : "graph"); + in >> Ignore('{'); assert(in); edge_property_type defaultEdgeProp; @@ -243,7 +294,7 @@ std::istream& read_dot(std::istream& in, Graph& g, BetterEP betterEP) } } else if (c == '-') { // Edge - in >> expect(">"); + in >> expect(isDirectedGraph ? ">" : "-"); assert(in); g_contigNames.lock(); diff --git a/Graph/GraphIO.h b/Graph/GraphIO.h index 78370e3..c8da010 100644 --- a/Graph/GraphIO.h +++ b/Graph/GraphIO.h @@ -53,7 +53,8 @@ std::istream& read_graph(std::istream& in, ContigGraph<Graph>& g, switch (in.peek()) { case '@': // @SQ: SAM format return read_sam_header(in, g); - case 'd': // digraph: GraphViz dot format + case 'd': // digraph: GraphViz dot format (directed graph) + case 'g': // graph: GraphViz dot format (undirected graph) return read_dot<Graph>(in, g, betterEP); case 'H': { in.get(); diff --git a/Graph/Makefile.am b/Graph/Makefile.am index cce5dd0..5a25efd 100644 --- a/Graph/Makefile.am +++ b/Graph/Makefile.am @@ -35,7 +35,8 @@ EXTRA_DIST = \ Path.h \ PopBubbles.h \ Properties.h \ - SAMIO.h + SAMIO.h \ + UndirectedGraph.h abyss_gc_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/Common abyss_gc_LDADD = $(top_builddir)/Common/libcommon.a diff --git a/Graph/SAMIO.h b/Graph/SAMIO.h index 5a20270..2d99b31 100644 --- a/Graph/SAMIO.h +++ b/Graph/SAMIO.h @@ -1,6 +1,7 @@ #ifndef SAMIO_H #define SAMIO_H 1 +#include "Common/ContigNode.h" #include "Graph/Properties.h" #include <istream> #include <sstream> diff --git a/Graph/UndirectedGraph.h b/Graph/UndirectedGraph.h new file mode 100644 index 0000000..1be38eb --- /dev/null +++ b/Graph/UndirectedGraph.h @@ -0,0 +1,948 @@ +#ifndef UNDIRECTEDGRAPH_H +#define UNDIRECTEDGRAPH_H 1 + +#include "Common/ContigNode.h" +#include "Common/Hash.h" +#include "Graph/Properties.h" +#include <algorithm> +#include <cassert> +#include <utility> +#include <vector> +#include <iostream> + +/** + * An edge for an undirected graph, having the key property that + * (u, v) == (v, u). The unsigned values here are the vertex_descriptor's. + */ +class UndirectedEdge : public std::pair<unsigned, unsigned> +{ + +public: + + UndirectedEdge() : std::pair<unsigned, unsigned>() {} + + UndirectedEdge(unsigned u, unsigned v) + : std::pair<unsigned, unsigned>(u, v) {} + + bool operator ==(const UndirectedEdge& e) const + { + return (first == e.first && second == e.second) || + (first == e.second && second == e.first); + } + + bool operator !=(const UndirectedEdge& e) const + { + return !(*this == e); + } + + size_t hashCode() const + { + return first ^ second; + } +}; + +/** + * The hash function for an undirected edge, having the key property that + * hash(u, v) == hash(v, u). + */ +NAMESPACE_STD_HASH_BEGIN +template <> struct hash<UndirectedEdge> { + /** + * Hash function for graph vertex type (vertex_descriptor) + */ + size_t operator()(const UndirectedEdge& e) const + { + return e.hashCode(); + } +}; +NAMESPACE_STD_HASH_END + +/** A undirected graph. */ +template <typename VertexProp = no_property, + typename EdgeProp = no_property> +class UndirectedGraph +{ + class Vertex; + typedef typename std::vector<Vertex> Vertices; + class Edge; + typedef typename std::vector<Edge> Edges; + + public: + // Graph + /* typedef ContigNode vertex_descriptor; */ + typedef unsigned vertex_descriptor; + + // IncidenceGraph + typedef UndirectedEdge edge_descriptor; + + typedef unsigned degree_size_type; + + // BidirectionalGraph + typedef void in_edge_iterator; + + // VertexListGraph + typedef unsigned vertices_size_type; + + // EdgeListGraph + typedef unsigned edges_size_type; + + // PropertyGraph + typedef VertexProp vertex_bundled; + typedef VertexProp vertex_property_type; + typedef EdgeProp edge_bundled; + typedef EdgeProp edge_property_type; + + typedef boost::undirected_tag directed_category; + typedef boost::allow_parallel_edge_tag edge_parallel_category; + struct traversal_category + : boost::incidence_graph_tag, + boost::adjacency_graph_tag, + boost::vertex_list_graph_tag, + boost::edge_list_graph_tag { }; + +/** Iterate through the vertices of this graph. */ +class vertex_iterator + : public std::iterator<std::input_iterator_tag, + const vertex_descriptor> +{ + public: + vertex_iterator() { } + explicit vertex_iterator(vertices_size_type v) : m_v(v) { } + const vertex_descriptor& operator *() const { return m_v; } + + bool operator ==(const vertex_iterator& it) const + { + return m_v == it.m_v; + } + + bool operator !=(const vertex_iterator& it) const + { + return m_v != it.m_v; + } + + vertex_iterator& operator ++() { ++m_v; return *this; } + vertex_iterator operator ++(int) + { + vertex_iterator it = *this; + ++*this; + return it; + } + + private: + vertex_descriptor m_v; +}; + +/** Iterate through the out-edges. */ +class out_edge_iterator + : public std::iterator<std::input_iterator_tag, edge_descriptor> +{ + typedef typename Edges::const_iterator const_iterator; + + public: + out_edge_iterator() { } + out_edge_iterator(const const_iterator& it, + vertex_descriptor src) : m_it(it), m_src(src) { } + + edge_descriptor operator *() const + { + return edge_descriptor(m_src, m_it->target()); + } + + bool operator ==(const out_edge_iterator& it) const + { + return m_it == it.m_it; + } + + bool operator !=(const out_edge_iterator& it) const + { + return m_it != it.m_it; + } + + out_edge_iterator& operator ++() { ++m_it; return *this; } + out_edge_iterator operator ++(int) + { + out_edge_iterator it = *this; + ++*this; + return it; + } + + const edge_property_type& get_property() const + { + return m_it->get_property(); + } + + private: + const_iterator m_it; + vertex_descriptor m_src; +}; + +/** Iterate through adjacent vertices. */ +class adjacency_iterator : public Edges::const_iterator +{ + typedef typename Edges::const_iterator It; + public: + adjacency_iterator() { } + adjacency_iterator(const It& it) : It(it) { } + vertex_descriptor operator*() const + { + return It::operator*().target(); + } +}; + +/** Iterate through edges. */ +class edge_iterator + : public std::iterator<std::input_iterator_tag, edge_descriptor> +{ + void nextVertex() + { + vertex_iterator vlast = m_g->vertices().second; + for (; m_vit != vlast; ++m_vit) { + std::pair<adjacency_iterator, adjacency_iterator> + adj = m_g->adjacent_vertices(*m_vit); + /* + * Since each edge exists as both (u, v) and + * (v, u), require `adj.first >= *m_vit` to visit only + * one of the two possible forms. + */ + if (adj.first != adj.second && *adj.first >= *m_vit) { + m_eit = adj.first; + return; + } + } + // Set m_eit to a known value. + static const adjacency_iterator s_eitNULL; + m_eit = s_eitNULL; + } + + public: + edge_iterator() { } + edge_iterator(const UndirectedGraph* g, const vertex_iterator& vit) + : m_g(g), m_vit(vit) + { + nextVertex(); + } + + edge_descriptor operator*() const + { + return edge_descriptor(*m_vit, *m_eit); + } + + bool operator==(const edge_iterator& it) const + { + return m_vit == it.m_vit && m_eit == it.m_eit; + } + + bool operator!=(const edge_iterator& it) const + { + return !(*this == it); + } + + edge_iterator& operator++() + { + if (++m_eit == m_g->adjacent_vertices(*m_vit).second) { + ++m_vit; + nextVertex(); + } + return *this; + } + + edge_iterator operator++(int) + { + edge_iterator it = *this; + ++*this; + return it; + } + + private: + const UndirectedGraph* m_g; + vertex_iterator m_vit; + adjacency_iterator m_eit; +}; + + private: +/** A vertex and its properties. */ +class Vertex +{ + public: + Vertex() { } + Vertex(const vertex_property_type& p) : m_prop(p) { } + + /** Return the properties of this vertex. */ + const vertex_property_type& get_property() const + { + return m_prop; + } + + /** Returns an iterator-range to the out edges of vertex u. */ + std::pair<out_edge_iterator, out_edge_iterator> + out_edges(vertex_descriptor u) const + { + return make_pair(out_edge_iterator(m_edges.begin(), u), + out_edge_iterator(m_edges.end(), u)); + } + + /** Returns an iterator-range to the adjacent vertices. */ + std::pair<adjacency_iterator, adjacency_iterator> + adjacent_vertices() const + { + return make_pair(m_edges.begin(), m_edges.end()); + } + + /** Return the number of outgoing edges. */ + degree_size_type out_degree() const + { + return m_edges.size(); + } + + /** Add an edge to this vertex. */ + bool add_edge(vertex_descriptor v, const edge_property_type& ep) + { + m_edges.push_back(Edge(v, ep)); + return true; + } + + /** Remove the edge to v from this vertex. */ + void remove_edge(vertex_descriptor v) + { + m_edges.erase(remove(m_edges.begin(), m_edges.end(), v), + m_edges.end()); + } + + /** Remove all out edges from this vertex. */ + void clear_out_edges() + { + m_edges.clear(); + } + + /** Return the properties of the edge with target v. */ + edge_property_type& operator[](vertex_descriptor v) + { + typename Edges::iterator it + = find(m_edges.begin(), m_edges.end(), v); + assert(it != m_edges.end()); + return it->get_property(); + } + + /** Return the properties of the edge with target v. */ + const edge_property_type& operator[](vertex_descriptor v) const + { + typename Edges::const_iterator it + = find(m_edges.begin(), m_edges.end(), v); + assert(it != m_edges.end()); + return it->get_property(); + } + + /** Return true if edge (u,v) exists. */ + bool edge(vertex_descriptor v) const + { + return count(m_edges.begin(), m_edges.end(), v) > 0; + } + + /** Remove edges that satisfy the predicate. */ + template <typename Predicate> + void remove_edge_if(vertex_descriptor u, Predicate predicate) + { + typename Edges::iterator out = m_edges.begin(); + for (typename Edges::iterator it = m_edges.begin(); + it != m_edges.end(); ++it) { + if (!predicate(edge_descriptor(u, it->target()))) { + if (out != it) + *out = *it; + ++out; + } + } + m_edges.erase(out, m_edges.end()); + } + + private: + Edges m_edges; + vertex_property_type m_prop; +}; + +/** A directed edge. */ +class Edge +{ + public: + explicit Edge(vertex_descriptor v, const edge_property_type& ep) + : m_target(v), m_ep(ep) { } + + /** Returns the target vertex of this edge. */ + vertex_descriptor target() const { return m_target; } + + /** Return true if the target of this edge is v. */ + bool operator ==(const vertex_descriptor& v) const + { + return m_target == v; + } + + edge_property_type& get_property() { return m_ep; } + const edge_property_type& get_property() const { return m_ep; } + + private: + /** The target vertex of this edge. */ + vertex_descriptor m_target; + edge_property_type m_ep; +}; + + public: + /** Create an empty graph. */ + UndirectedGraph() { } + + /** Create a graph with n vertices and zero edges. */ + UndirectedGraph(vertices_size_type n) : m_vertices(n) { } + + /** Swap this graph with graph x. */ + void swap(UndirectedGraph& x) + { + m_vertices.swap(x.m_vertices); + m_removed.swap(x.m_removed); + } + + /** Return properties of vertex u. */ + const vertex_property_type& operator[](vertex_descriptor u) const + { + vertices_size_type ui = get(vertex_index, *this, u); + assert(ui < num_vertices()); + return m_vertices[ui].get_property(); + } + + /** Returns an iterator-range to the vertices. */ + std::pair<vertex_iterator, vertex_iterator> vertices() const + { + return make_pair(vertex_iterator(0), + vertex_iterator(num_vertices())); + } + + /** Remove all the edges and vertices from this graph. */ + void clear() { m_vertices.clear(); m_removed.clear(); } + + /** Add a vertex to this graph. */ + vertex_descriptor add_vertex( + const vertex_property_type& vp = vertex_property_type()) + { + m_vertices.push_back(Vertex(vp)); + return vertex_descriptor(num_vertices() - 1); + } + + /** Returns an iterator-range to the out edges of vertex u. */ + std::pair<out_edge_iterator, out_edge_iterator> + out_edges(vertex_descriptor u) const + { + vertices_size_type ui = get(vertex_index, *this, u); + assert(ui < num_vertices()); + return m_vertices[ui].out_edges(u); + } + + /** Returns an iterator-range to the adjacent vertices of + * vertex u. */ + std::pair<adjacency_iterator, adjacency_iterator> + adjacent_vertices(vertex_descriptor u) const + { + vertices_size_type ui = get(vertex_index, *this, u); + assert(ui < num_vertices()); + return m_vertices[ui].adjacent_vertices(); + } + + /** Adds edge (u,v) to this graph. */ + std::pair<edge_descriptor, bool> + add_edge(vertex_descriptor u, vertex_descriptor v, + const edge_property_type& ep = edge_property_type()) + { + vertices_size_type ui = get(vertex_index, *this, u); + assert(ui < num_vertices()); + vertices_size_type vi = get(vertex_index, *this, v); + assert(vi < num_vertices()); + m_vertices[vi].add_edge(u, ep); + return make_pair(edge_descriptor(u, v), + m_vertices[ui].add_edge(v, ep)); + } + + /** Remove the edge (u,v) from this graph. */ + void remove_edge(vertex_descriptor u, vertex_descriptor v) + { + vertices_size_type ui = get(vertex_index, *this, u); + assert(ui < num_vertices()); + vertices_size_type vi = get(vertex_index, *this, v); + assert(vi < num_vertices()); + m_vertices[ui].remove_edge(v); + m_vertices[ui].remove_edge(u); + } + + /** Remove the edge e from this graph. */ + void remove_edge(edge_descriptor e) + { + remove_edge(e.first, e.second); + } + +#if 0 + /** Remove all out edges from vertex u. */ + void clear_out_edges(vertex_descriptor u) + { + vertices_size_type ui = get(vertex_index, *this, u); + assert(ui < num_vertices()); + m_vertices[ui].clear_out_edges(); + } +#endif + + /** Remove all edges to and from vertex u from this graph. + * O(V+E) */ + void clear_vertex(vertex_descriptor u) + { + std::pair<adjacency_iterator, adjacency_iterator> + adj = adjacent_vertices(u); + for (adjacency_iterator v = adj.first; v != adj.second; ++v) + remove_edge(*v, u); + } + + /** Set the vertex_removed property. */ + void put(vertex_removed_t, vertex_descriptor u, bool flag) + { + vertices_size_type ui = get(vertex_index, *this, u); + if (ui >= m_removed.size()) + m_removed.resize(ui + 1); + m_removed[ui] = flag; + } + + /** Remove vertex u from this graph. It is assumed that there + * are no edges to or from vertex u. It is best to call + * clear_vertex before remove_vertex. + */ + void remove_vertex(vertex_descriptor u) + { + put(vertex_removed, u, true); + } + + /** Return the number of vertices. */ + vertices_size_type num_vertices() const + { + return m_vertices.size(); + } + + /** Return the number of edges. */ + edges_size_type num_edges() const + { + edges_size_type n = 0; + std::pair<vertex_iterator, vertex_iterator> vit = vertices(); + for (vertex_iterator v = vit.first; v != vit.second; ++v) + n += out_degree(*v); + /* should have (u, v) and (v, u) versions for each edge */ + assert(n % 2 == 0); + return n / 2; + } + + /** Return the out degree of vertex u. */ + degree_size_type out_degree(vertex_descriptor u) const + { + vertices_size_type ui = get(vertex_index, *this, u); + assert(ui < num_vertices()); + return m_vertices[ui].out_degree(); + } + + /** Return the nth vertex. */ + static vertex_descriptor vertex(vertices_size_type n) + { + return vertex_descriptor(n); + } + + /** Iterate through the edges of this graph. */ + std::pair<edge_iterator, edge_iterator> edges() const + { + std::pair<vertex_iterator, vertex_iterator> vit = vertices(); + return make_pair(edge_iterator(this, vit.first), + edge_iterator(this, vit.second)); + } + + /** Return the edge (u,v) if it exists and a flag indicating + * whether the edge exists. + */ + std::pair<edge_descriptor, bool> edge( + vertex_descriptor u, vertex_descriptor v) const + { + vertices_size_type ui = get(vertex_index, *this, u); + assert(ui < num_vertices()); + return make_pair(edge_descriptor(u, v), + m_vertices[ui].edge(v)); + } + + /** Return properties of edge e. */ + edge_property_type& operator[](edge_descriptor e) + { + vertices_size_type ui = get(vertex_index, *this, e.first); + assert(ui < num_vertices()); + return m_vertices[ui][e.second]; + } + + /** Return properties of edge e. */ + const edge_property_type& operator[](edge_descriptor e) const + { + vertices_size_type ui = get(vertex_index, *this, e.first); + assert(ui < num_vertices()); + return m_vertices[ui][e.second]; + } + + /** Remove edges that satisfy the predicate. */ + template <typename Predicate> + void remove_edge_if(Predicate predicate) + { + unsigned i = 0; + for (typename Vertices::iterator it = m_vertices.begin(); + it != m_vertices.end(); ++it) + it->remove_edge_if(vertex(i++), predicate); + } + + /** Return true if this vertex has been removed. */ + bool is_removed(vertex_descriptor u) const + { + vertices_size_type ui = get(vertex_index, *this, u); + return ui < m_removed.size() ? m_removed[ui] : false; + } + + /** Set the name (usually contig ID) for a given vertex_descriptor */ + void put(vertex_name_t, vertex_descriptor u, const Dictionary::name_type& name) + { + m_vertexNames.put(u, name); + } + + /** Find a vertex_descriptor by name (usually contig ID) */ + vertex_descriptor find_vertex(const Dictionary::name_type& name) const + { + return m_vertexNames.getIndex(name); + } + + private: + UndirectedGraph& operator =(const UndirectedGraph& x); + + /** The set of vertices. */ + Vertices m_vertices; + + /** Bidirectional map of names to vertex_descriptors */ + Dictionary m_vertexNames; + + /** Flags indicating vertices that have been removed. */ + std::vector<bool> m_removed; +}; + +namespace std { + template <typename VertexProp, typename EdgeProp> + inline void swap(UndirectedGraph<VertexProp, EdgeProp>& a, + UndirectedGraph<VertexProp, EdgeProp>& b) { a.swap(b); } +} + +// IncidenceGraph + +template <typename VP, typename EP> +std::pair< + typename UndirectedGraph<VP, EP>::out_edge_iterator, + typename UndirectedGraph<VP, EP>::out_edge_iterator> +out_edges( + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + const UndirectedGraph<VP, EP>& g) +{ + return g.out_edges(u); +} + +template <typename VP, typename EP> +typename UndirectedGraph<VP, EP>::degree_size_type +out_degree( + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + const UndirectedGraph<VP, EP>& g) +{ + return g.out_degree(u); +} + +// AdjacencyGraph + +template <typename VP, typename EP> +std::pair< + typename UndirectedGraph<VP, EP>::adjacency_iterator, + typename UndirectedGraph<VP, EP>::adjacency_iterator> +adjacent_vertices( + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + const UndirectedGraph<VP, EP>& g) +{ + return g.adjacent_vertices(u); +} + +// VertexListGraph + +template <typename VP, typename EP> +typename UndirectedGraph<VP, EP>::vertices_size_type +num_vertices(const UndirectedGraph<VP, EP>& g) +{ + return g.num_vertices(); +} + +template <typename VP, typename EP> +typename UndirectedGraph<VP, EP>::vertex_descriptor +vertex(typename UndirectedGraph<VP, EP>::vertices_size_type ui, const UndirectedGraph<VP, EP>& g) +{ + return g.vertex(ui); +} + +template <typename VP, typename EP> +std::pair<typename UndirectedGraph<VP, EP>::vertex_iterator, + typename UndirectedGraph<VP, EP>::vertex_iterator> +vertices(const UndirectedGraph<VP, EP>& g) +{ + return g.vertices(); +} + +// EdgeListGraph + +template <typename VP, typename EP> +typename UndirectedGraph<VP, EP>::edges_size_type +num_edges(const UndirectedGraph<VP, EP>& g) +{ + return g.num_edges(); +} + +template <typename VP, typename EP> +std::pair<typename UndirectedGraph<VP, EP>::edge_iterator, + typename UndirectedGraph<VP, EP>::edge_iterator> +edges(const UndirectedGraph<VP, EP>& g) +{ + return g.edges(); +} + +// AdjacencyMatrix + +template <typename VP, typename EP> +std::pair<typename UndirectedGraph<VP, EP>::edge_descriptor, bool> +edge( + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + typename UndirectedGraph<VP, EP>::vertex_descriptor v, + const UndirectedGraph<VP, EP>& g) +{ + return g.edge(u, v); +} + +// VertexMutableGraph + +template <typename VP, typename EP> +typename UndirectedGraph<VP, EP>::vertex_descriptor +add_vertex(UndirectedGraph<VP, EP>& g) +{ + return g.add_vertex(); +} + +template <typename VP, typename EP> +void +remove_vertex( + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + UndirectedGraph<VP, EP>& g) +{ + g.remove_vertex(u); +} + +// EdgeMutableGraph + +template <typename VP, typename EP> +void +clear_vertex( + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + UndirectedGraph<VP, EP>& g) +{ + g.clear_vertex(u); +} + +template <typename VP, typename EP> +std::pair<typename UndirectedGraph<VP, EP>::edge_descriptor, bool> +add_edge( + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + typename UndirectedGraph<VP, EP>::vertex_descriptor v, + UndirectedGraph<VP, EP>& g) +{ + return g.add_edge(u, v); +} + +template <typename VP, typename EP> +void +remove_edge( + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + typename UndirectedGraph<VP, EP>::vertex_descriptor v, + UndirectedGraph<VP, EP>& g) +{ + g.remove_edge(u, v); +} + +template <typename VP, typename EP> +void +remove_edge( + typename UndirectedGraph<VP, EP>::edge_descriptor e, + UndirectedGraph<VP, EP>& g) +{ + g.remove_edge(e); +} + +// MutableIncidenceGraph + +template <typename VP, typename EP> +void +clear_out_edges( + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + UndirectedGraph<VP, EP>& g) +{ + g.clear_out_edges(u); +} + +// MutableEdgeListGraph + +template <typename VP, typename EP, class Predicate> +void +remove_edge_if(Predicate predicate, UndirectedGraph<VP, EP>& g) +{ + g.remove_edge_if(predicate); +} + +// PropertyGraph + +/** Return true if this vertex has been removed. */ +template <typename VP, typename EP> +bool get(vertex_removed_t, const UndirectedGraph<VP, EP>& g, + typename UndirectedGraph<VP, EP>::vertex_descriptor u) +{ + return g.is_removed(u); +} + +template <typename VP, typename EP> +void put(vertex_removed_t tag, UndirectedGraph<VP, EP>& g, + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + bool flag) +{ + g.put(tag, u, flag); +} + +/** Return the properties of the edge of iterator eit. */ +template <typename VP, typename EP> +const typename UndirectedGraph<VP, EP>::edge_property_type& +get(edge_bundle_t, const UndirectedGraph<VP, EP>&, + typename UndirectedGraph<VP, EP>::out_edge_iterator eit) +{ + return eit.get_property(); +} + +// PropertyGraph + +template <typename VP, typename EP> +const VP& +get(vertex_bundle_t, const UndirectedGraph<VP, EP>& g, + typename UndirectedGraph<VP, EP>::vertex_descriptor u) +{ + return g[u]; +} + +template <typename VP, typename EP> +const EP& +get(edge_bundle_t, const UndirectedGraph<VP, EP>& g, + typename UndirectedGraph<VP, EP>::edge_descriptor e) +{ + return g[e]; +} + +// PropertyGraph vertex_index + +#if 0 +namespace boost { +template <typename VP, typename EP> +struct property_map<UndirectedGraph<VP, EP>, vertex_index_t> +{ + typedef ContigNodeIndexMap type; + typedef type const_type; +}; +} + +template <typename VP, typename EP> +ContigNodeIndexMap +get(vertex_index_t, const UndirectedGraph<VP, EP>&) +{ + return ContigNodeIndexMap(); +} + +template <typename VP, typename EP> +ContigNodeIndexMap::reference +get(vertex_index_t tag, const UndirectedGraph<VP, EP>& g, + typename UndirectedGraph<VP, EP>::vertex_descriptor u) +{ + return get(get(tag, g), u); +} +#endif + +// VertexMutablePropertyGraph + +template <typename VP, typename EP> +typename UndirectedGraph<VP, EP>::vertex_descriptor +add_vertex(const VP& vp, UndirectedGraph<VP, EP>& g) +{ + return g.add_vertex(vp); +} + +// EdgeMutablePropertyGraph + +template <typename VP, typename EP> +std::pair<typename UndirectedGraph<VP, EP>::edge_descriptor, bool> +add_edge( + typename UndirectedGraph<VP, EP>::vertex_descriptor u, + typename UndirectedGraph<VP, EP>::vertex_descriptor v, + const typename UndirectedGraph<VP, EP>::edge_property_type& ep, + UndirectedGraph<VP, EP>& g) +{ + return g.add_edge(u, v, ep); +} + +// NamedGraph + +template <typename VP, typename EP> +typename UndirectedGraph<VP, EP>::vertex_descriptor +find_vertex(const std::string& name, const UndirectedGraph<VP, EP>& g) +{ + /* return find_vertex(name, g_contigNames); */ + return g.find_vertex(name); +} + +#if 0 +template <typename VP, typename EP> +typename UndirectedGraph<VP, EP>::vertex_descriptor +find_vertex(const std::string& name, bool sense, + const UndirectedGraph<VP, EP>&) +{ + return find_vertex(name, sense, g_contigNames); +} +#endif + +/** + * Get the index of a vertex in UndirectedGraph's + * internal data structures (vertex list and + * vertex_descriptor => vertex_name map). + */ +template <typename VP, typename EP> +typename UndirectedGraph<VP, EP>::vertices_size_type +get(vertex_index_t, const UndirectedGraph<VP, EP>&, + typename UndirectedGraph<VP, EP>::vertex_descriptor u) +{ + /* + * For UndirectedGraph, vertex_index and vertex_descriptor + * are always the same, where `vertex_index` indicates the position of + * the vertex in UndirectedGraph's vertex list (`m_vertices` above) + * and also the position of the vertex in the + * vertex_name <=> vertex_descriptor map (`m_vertexNames` above). + * + * For DirectedGraph, vertex_index and vertex_descriptor are + * different types (unsigned and ContigNode, respectively), because + * vertex names end with "+" or "-". + */ + return u; +} + +/** + * Set the name for a vertex. This is a std::string and usually + * stores the contig ID. + */ +template <typename VP, typename EP> +void put(vertex_name_t tag, UndirectedGraph<VP, EP>& g, + typename UndirectedGraph<VP, EP>::vertex_descriptor& u, + const Dictionary::name_type& name) +{ + g.put(tag, u, name); +} + +#endif diff --git a/Konnector/DBGBloom.h b/Konnector/DBGBloom.h index e3defdd..d72c033 100644 --- a/Konnector/DBGBloom.h +++ b/Konnector/DBGBloom.h @@ -346,6 +346,15 @@ in_degree(typename graph_traits<Graph>::vertex_descriptor u, template <typename Graph> static inline +typename graph_traits<Graph>::degree_size_type +degree(typename graph_traits<Graph>::vertex_descriptor u, + const Graph& g) +{ + return in_degree(u, g) + out_degree(u, g); +} + +template <typename Graph> +static inline std::pair<typename graph_traits<Graph>::in_edge_iterator, typename graph_traits<Graph>::in_edge_iterator> in_edges( diff --git a/README.md b/README.md index 4765389..272a82e 100644 --- a/README.md +++ b/README.md @@ -248,21 +248,27 @@ Assembling using a Bloom filter de Bruijn graph ========================================= Assemblies may be performed using a _Bloom filter de Bruijn graph_, which -typically reduces memory requirements by an order of magnitude. In order to -assemble in Bloom filter mode, the user must specify 3 additional parameters: -`B` (Bloom filter size), `H` (number of Bloom filter hash functions), and `kc` -(minimum k-mer count threshold). Valid size units for the `B` parameter are 'k', -'M', 'G'. If no unit is specified, bytes are assumed. For example, the following -will run a E. coli assembly with a Bloom filter size of 100 MB, 3 hash -functions, a minimum k-mer count threshold of 3, and verbose logging: +typically reduces memory requirements by an order of magnitude. To assemble in +Bloom filter mode, the user must specify 3 additional parameters: `B` (Bloom +filter size in bytes), `H` (number of Bloom filter hash functions), and `kc` +(minimum k-mer count threshold). `B` is the overall memory budget for the Bloom +filter assembler, and may be specified with unit suffixes 'k' (kilobytes), 'M' +(megabytes), 'G' (gigabytes). If no units are specified bytes are assumed. For +example, the following will run a E. coli assembly with an overall memory budget +of 100 megabytes, 3 hash functions, a minimum k-mer count threshold of 3, with +verbose logging enabled: abyss-pe name=ecoli k=64 in='reads1.fa reads2.fa' B=100M H=3 kc=3 v=-v At the current time, the user must calculate suitable values for `B` and `H` on their own, and finding the best value for `kc` may require experimentation -(optimal values are typically in the range of 2-4). Users are recommended to -target a Bloom filter false positive rate (FPR) that is less than 5%, as -reported by the assembly log when using the `v=-v` option (verbose level 1). +(optimal values are typically in the range of 2-4). Internally, the Bloom filter +assembler divides the memory budget (`B`) equally across (`kc` + 1) Bloom +filters, where `kc` Bloom filters are used for the cascading Bloom filter and +one additional Bloom filter is used to track k-mers that have previously been +included in contigs. Users are recommended to target a Bloom filter false +positive rate (FPR) that is less than 5%, as reported by the assembly log when +using the `v=-v` option (verbose level 1). Assembling using a paired de Bruijn graph ========================================= diff --git a/Unittest/DBG/LoadAlgorithmTest.cpp b/Unittest/DBG/LoadAlgorithmTest.cpp index 8de2f39..d31e825 100644 --- a/Unittest/DBG/LoadAlgorithmTest.cpp +++ b/Unittest/DBG/LoadAlgorithmTest.cpp @@ -1,3 +1,4 @@ +#include "config.h" #include "Assembly/SequenceCollection.h" #include "Assembly/DBG.h" #include "Assembly/AssemblyAlgorithms.h" diff --git a/Unittest/Graph/DotIOTest.cpp b/Unittest/Graph/DotIOTest.cpp new file mode 100644 index 0000000..9a2083d --- /dev/null +++ b/Unittest/Graph/DotIOTest.cpp @@ -0,0 +1,115 @@ +#include "Common/ContigID.h" +#include "Common/Dictionary.h" +#include "Graph/GraphIO.h" +#include "Graph/DotIO.h" +#include "Graph/UndirectedGraph.h" +#include "Graph/DirectedGraph.h" +#include "Graph/Properties.h" +#include <boost/tuple/tuple.hpp> +#include <gtest/gtest.h> +#include <string> +#include <sstream> + +using namespace std; + +typedef UndirectedGraph<NoProperty, NoProperty> UGraph; +typedef boost::graph_traits<UGraph>::vertex_descriptor UV; +typedef boost::graph_traits<UGraph>::edge_descriptor UE; +typedef boost::graph_traits<UGraph>::edge_iterator UEIt; + +typedef DirectedGraph<NoProperty, NoProperty> DGraph; +typedef boost::graph_traits<DGraph>::vertex_descriptor DV; +typedef boost::graph_traits<DGraph>::edge_descriptor DE; +typedef boost::graph_traits<DGraph>::edge_iterator DEIt; + +TEST(DotIOTest, UndirectedGraph) +{ + /* reset state of global contig ID map */ + g_contigNames.clear(); + + string graphviz; + stringstream ss; + + /* undirected graph, unquoted IDs */ + + graphviz = + "graph {\n" + " a;\n" + " b;\n" + " a -- b;\n" + "}\n"; + + ss << graphviz; + ASSERT_TRUE(ss.good()); + + UGraph g; + read_dot(ss, g, DisallowParallelEdges()); + ASSERT_TRUE(!ss.fail()); + + /* check that correct graph structure was created */ + + ASSERT_EQ(2u, num_vertices(g)); + UV a = find_vertex("a", g); + ASSERT_LT(a, num_vertices(g)); + UV b = find_vertex("b", g); + ASSERT_LT(b, num_vertices(g)); + + ASSERT_EQ(1u, num_edges(g)); + UEIt ueit, ueit_end; + boost::tie(ueit, ueit_end) = edges(g); + ASSERT_NE(ueit, ueit_end); + UE e = UE(a, b); + ASSERT_EQ(e, *ueit); + ASSERT_TRUE(source(*ueit, g) == a || target(*ueit, g) == a); + ASSERT_TRUE(source(*ueit, g) == b || target(*ueit, g) == b); + ++ueit; + ASSERT_EQ(ueit, ueit_end); + +} + +TEST(DotIOTest, DirectedGraph) +{ + /* reset state of global contig ID map */ + g_contigNames.clear(); + + string graphviz; + stringstream ss; + + /* directed graph, quoted IDs */ + + graphviz = + "digraph {\n" + " \"1+\";\n" + " \"1-\";\n" + " \"2+\";\n" + " \"2-\";\n" + " \"1+\" -> \"2-\";\n" + "}\n"; + + ss << graphviz; + ASSERT_TRUE(ss.good()); + + DGraph g; + read_dot(ss, g, DisallowParallelEdges()); + ASSERT_TRUE(!ss.fail()); + + /* check that correct graph structure was created */ + + ASSERT_EQ(4u, num_vertices(g)); + DV v1 = find_vertex("1+", g); + ASSERT_LT(v1.index(), num_vertices(g)); + DV v2 = find_vertex("2-", g); + ASSERT_LT(v2.index(), num_vertices(g)); + + ASSERT_EQ(1u, num_edges(g)); + DEIt ueit, ueit_end; + boost::tie(ueit, ueit_end) = edges(g); + ASSERT_NE(ueit, ueit_end); + DE e = DE(v1, v2); + ASSERT_EQ(e, *ueit); + ASSERT_TRUE(source(*ueit, g) == v1); + ASSERT_TRUE(target(*ueit, g) == v2); + ++ueit; + ASSERT_EQ(ueit, ueit_end); + +} diff --git a/Unittest/Graph/UndirectedGraphTest.cpp b/Unittest/Graph/UndirectedGraphTest.cpp new file mode 100644 index 0000000..0f3f295 --- /dev/null +++ b/Unittest/Graph/UndirectedGraphTest.cpp @@ -0,0 +1,54 @@ +#include "Common/Hash.h" +#include "Graph/UndirectedGraph.h" +#include "Graph/Properties.h" +#include <boost/tuple/tuple.hpp> +#include <gtest/gtest.h> +#include <string> +#include <sstream> + +using namespace std; + +typedef UndirectedGraph<NoProperty, NoProperty> Graph; +typedef boost::graph_traits<Graph>::vertex_descriptor V; +typedef boost::graph_traits<Graph>::edge_descriptor E; +typedef boost::graph_traits<Graph>::edge_iterator EdgeIterator; + +TEST(UndirectedGraphTest, edgeComparison) +{ + Graph g; + V u = add_vertex(NoProperty(), g); + V v = add_vertex(NoProperty(), g); + E uv = E(u, v); + E vu = E(v, u); + ASSERT_EQ(uv, vu); + ASSERT_EQ(uv.hashCode(), vu.hashCode()); +} + +TEST(UndirectedGraphTest, edges) +{ + Graph g; + + V u = add_vertex(NoProperty(), g); + V v = add_vertex(NoProperty(), g); + + /* + * Internally, both edge orientations (u, v) and (v, u) are + * added to the graph data structures. Make sure that + * this isn't exposed externally and that we only see one edge. + */ + + E e; + bool inserted; + boost::tie(e, inserted) = add_edge(u, v, NoProperty(), g); + ASSERT_TRUE(inserted); + ASSERT_EQ(1u, num_edges(g)); + + /* make sure iterator only visits one version of the edge */ + + EdgeIterator eit, eit_end; + boost::tie(eit, eit_end) = edges(g); + ASSERT_NE(eit, eit_end); + ASSERT_EQ(e, *eit); + ++eit; + ASSERT_EQ(eit, eit_end); +} diff --git a/Unittest/Makefile.am b/Unittest/Makefile.am index da0980f..b8770ca 100644 --- a/Unittest/Makefile.am +++ b/Unittest/Makefile.am @@ -5,6 +5,7 @@ AM_CXXFLAGS += $(PTHREAD_CFLAGS) -Wno-error AM_LDFLAGS = $(PTHREAD_LIBS) AM_CPPFLAGS = \ + -DGTEST_USE_OWN_TR1_TUPLE=0 \ -I$(top_srcdir) \ -I$(top_srcdir)/lib/gtest-1.7.0/include LDADD = $(top_builddir)/lib/gtest-1.7.0/libgtest_main.a @@ -83,6 +84,20 @@ graph_ExtendPath_SOURCES = Graph/ExtendPathTest.cpp graph_ExtendPath_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/Common graph_ExtendPath_LDADD = $(top_builddir)/Common/libcommon.a $(LDADD) +check_PROGRAMS += graph_DotIO +graph_DotIO_SOURCES = Graph/DotIOTest.cpp +graph_DotIO_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/Common +graph_DotIO_LDADD = \ + $(top_builddir)/Assembly/libassembly.a \ + $(top_builddir)/DataLayer/libdatalayer.a \ + $(top_builddir)/Common/libcommon.a \ + $(LDADD) + +check_PROGRAMS += graph_UndirectedGraph +graph_UndirectedGraph_SOURCES = Graph/UndirectedGraphTest.cpp +# graph_UndirectedGraph_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/Common +# graph_UndirectedGraph_LDADD = $(top_builddir)/Common/libcommon.a $(LDADD) + check_PROGRAMS += Konnector_konnector Konnector_konnector_SOURCES = \ Konnector/konnectorTest.cpp diff --git a/configure.ac b/configure.ac index 884852b..4b8df12 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.62) -AC_INIT(ABySS, 2.0.1, [email protected], abyss, +AC_INIT(ABySS, 2.0.2, [email protected], abyss, http://www.bcgsc.ca/platform/bioinfo/software/abyss) m4_include(m4/m4_ax_pthread.m4) AM_INIT_AUTOMAKE(1.9.6 foreign subdir-objects) @@ -55,6 +55,17 @@ AC_CHECK_TYPE([std::tr1::hash<int>], AC_DEFINE(HAVE_STD_TR1_HASH, [1], [Define if the system provides std::tr1::hash]), [], [#include <tr1/functional>]) +AC_CHECK_TYPE([std::tr1::tuple<int>], + AC_DEFINE(HAVE_STD_TR1_TUPLE, [1], + [Define if the system provides std::tr1::tuple]), + [], [#include <tr1/tuple>]) +if test "x$ac_cv_type_std__tr1__tuple_int_" = "xyes"; then + # Avoid double-declaration of std::tr1::tuple by boost. + # See http://stackoverflow.com/questions/1156003/c-namespace-collision-with-gtest-and-boost + # for explanation. + AC_DEFINE(BOOST_HAS_TR1_TUPLE, [1], + [Define to disable declaration of std::tr1::tuple by boost]) +fi AC_LANG_POP([C++]) # Checks for library functions. diff --git a/doc/ABYSS.1 b/doc/ABYSS.1 index 14a9f69..8f3a30a 100644 --- a/doc/ABYSS.1 +++ b/doc/ABYSS.1 @@ -1,4 +1,4 @@ -.TH ABYSS "1" "2015-May" "ABYSS (ABySS) 2.0.1" "User Commands" +.TH ABYSS "1" "2015-May" "ABYSS (ABySS) 2.0.2" "User Commands" .SH NAME ABYSS \- assemble short reads into contigs .SH SYNOPSIS diff --git a/doc/abyss-pe.1 b/doc/abyss-pe.1 index fb94fe7..e6af3d7 100644 --- a/doc/abyss-pe.1 +++ b/doc/abyss-pe.1 @@ -1,4 +1,4 @@ -.TH abyss-pe "1" "2015-May" "abyss-pe (ABySS) 2.0.1" "User Commands" +.TH abyss-pe "1" "2015-May" "abyss-pe (ABySS) 2.0.2" "User Commands" .SH NAME abyss-pe - assemble reads into contigs .SH SYNOPSIS diff --git a/doc/abyss-tofastq.1 b/doc/abyss-tofastq.1 index 4250191..d8fd0ea 100644 --- a/doc/abyss-tofastq.1 +++ b/doc/abyss-tofastq.1 @@ -1,4 +1,4 @@ -.TH abyss-tofastq "1" "2015-May" "ABySS 2.0.1" "User Commands" +.TH abyss-tofastq "1" "2015-May" "ABySS 2.0.2" "User Commands" .SH NAME abyss-tofastq \- convert various file formats to FASTQ format .br diff --git a/doc/flowchart.graffle b/doc/flowchart.graffle index a695117..73a03b0 100644 --- a/doc/flowchart.graffle +++ b/doc/flowchart.graffle @@ -5198,7 +5198,7 @@ {\colortbl;\red255\green255\blue255;} \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc -\f0\b\fs28 \cf0 ABySS paired-end pipeline version 2.0.1}</string> +\f0\b\fs28 \cf0 ABySS paired-end pipeline version 2.0.2}</string> <key>VerticalPad</key> <integer>0</integer> </dict> -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/abyss.git _______________________________________________ debian-med-commit mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-med-commit
