#ifndef DOTIO_H #define DOTIO_H 1 #include "ContigID.h" // for g_contigNames.lock #include "Graph/Options.h" #include "IOUtil.h" #include #include #include // for exit #include #include using boost::graph_traits; template void write_vertex(std::ostream& out, const Graph& g, typename graph_traits::vertex_descriptor u, const VertexProp*) { out << '"' << get(vertex_name, g, u) << "\"" " [" << get(vertex_bundle, g, u) << "]\n"; } template void write_vertex(std::ostream&, const Graph&, typename graph_traits::vertex_descriptor, const no_property*) { } template void write_edges(std::ostream& out, const Graph& g, typename graph_traits::vertex_descriptor u, const EdgeProp*) { typedef typename graph_traits::out_edge_iterator out_edge_iterator; typedef typename edge_property::type edge_property_type; std::pair adj = out_edges(u, g); for (out_edge_iterator e = adj.first; e != adj.second; ++e) { assert(!get(vertex_removed, g, target(*e, g))); out << get(edge_name, g, *e); const edge_property_type& ep = get(edge_bundle, g, e); if (!(ep == edge_property_type())) out << " [" << ep << ']'; out << '\n'; } } template void write_edges(std::ostream& out, const Graph& g, typename graph_traits::vertex_descriptor u, const no_property*) { typedef typename graph_traits::adjacency_iterator adjacency_iterator; unsigned outdeg = out_degree(u, g); if (outdeg == 0) return; out << '"' << get(vertex_name, g, u) << "\" ->"; if (outdeg > 1) out << " {"; std::pair adj = adjacent_vertices(u, g); for (adjacency_iterator v = adj.first; v != adj.second; ++v) out << " \"" << get(vertex_name, g, *v) << '"'; if (outdeg > 1) out << " }"; out << '\n'; } /** Output a GraphViz dot graph. */ template std::ostream& write_dot(std::ostream& out, const Graph& g) { return write_dot(out, g, "adj"); } /** Output a GraphViz dot graph. */ template std::ostream& write_dot(std::ostream& out, const Graph& g, const std::string& graphName) { typedef typename graph_traits::vertex_iterator vertex_iterator; typedef typename vertex_property::type vertex_property_type; typedef typename edge_property::type edge_property_type; out << "digraph " << graphName << " {\n"; // Graph properties if (opt::k > 0) out << "graph [k=" << opt::k << "]\n" "edge [d=" << -int(opt::k - 1) << "]\n"; // Vertices std::pair vit = vertices(g); for (vertex_iterator u = vit.first; u != vit.second; ++u) { if (get(vertex_removed, g, *u)) continue; write_vertex(out, g, *u, (vertex_property_type*)NULL); } // Edges for (vertex_iterator u = vit.first; u != vit.second; ++u) { if (get(vertex_removed, g, *u)) continue; write_edges(out, g, *u, (edge_property_type*)NULL); } return out << "}\n"; } /** Output a GraphViz dot graph. */ template struct DotWriter { const Graph& g; DotWriter(const Graph& g) : g(g) { } friend std::ostream& operator<<(std::ostream& out, const DotWriter& o) { return write_dot(out, o.g); } }; /** Output a GraphViz dot graph. */ template DotWriter dot_writer(const Graph& g) { return DotWriter(g); } /** 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.get(); getline(in, s, '"'); } else in.clear(std::ios::failbit); return in; } /** Read a vertex descriptor delimited by double quotes. */ template std::istream& read_dot_id(std::istream& in, const Graph& g, typename graph_traits::vertex_descriptor& u) { std::string s; if (read_dot_name(in, s)) u = find_vertex(s, g); return in; } /** Read a GraphViz dot graph. * @param betterEP handle parallel edges */ template std::istream& read_dot(std::istream& in, Graph& g, BetterEP betterEP) { assert(in); typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename vertex_property::type vertex_property_type; typedef typename graph_traits::edge_descriptor edge_descriptor; typedef typename edge_property::type edge_property_type; typedef typename graph_traits::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(isDirectedGraph ? "digraph" : "graph"); in >> Ignore('{'); assert(in); edge_property_type defaultEdgeProp; for (bool done = false; !done && in >> std::ws;) { switch (in.peek()) { case 'g': { // Graph Properties in >> expect("graph [ "); if (in.peek() == 'k') { unsigned k; in >> expect("k =") >> k; assert(in); if (opt::k > 0) assert(k == opt::k); opt::k = k; } in >> Ignore(']'); break; } case 'e': // edge // Default edge properties in >> expect("edge [") >> defaultEdgeProp >> Ignore(']'); assert(in); break; default: done = true; break; } if (in >> std::ws && in.peek() == ';') in.get(); } for (std::string uname; read_dot_name(in, uname);) { char c; in >> c; assert(in); if (c == ';') { // Vertex if (addVertices) { vertex_descriptor u = add_vertex(g); put(vertex_name, g, u, uname); } else { vertex_descriptor u = find_vertex(uname, g); assert(get(vertex_index, g, u) < num_vertices(g)); (void)u; } } else if (c == '[') { // Vertex properties vertex_property_type vp; in >> vp >> Ignore(']'); assert(in); if (addVertices) { vertex_descriptor u = add_vertex(vp, g); put(vertex_name, g, u, uname); } else { vertex_descriptor u = find_vertex(uname, g); assert(get(vertex_index, g, u) < num_vertices(g)); if (g[u] != vp) { std::cerr << "error: " "vertex properties do not agree: " "\"" << uname << "\" " "[" << g[u] << "] [" << vp << "]\n"; exit(EXIT_FAILURE); } } } else if (c == '-') { // Edge in >> expect(isDirectedGraph ? ">" : "-"); assert(in); g_contigNames.lock(); vertex_descriptor u = find_vertex(uname, g); if (in >> std::ws && in.peek() == '{') { // Subgraph in >> expect("{"); for (vertex_descriptor v; read_dot_id(in, g, v);) add_edge(u, v, defaultEdgeProp, g); if (in.fail()) in.clear(); in >> expect(" }"); assert(in); } else { vertex_descriptor v; if (!read_dot_id(in, g, v)) { in.clear(); std::cerr << "error: Expected `\"' and saw `" << (char)in.peek() << "'.\n"; exit(EXIT_FAILURE); } assert(in); edge_property_type ep = defaultEdgeProp; if (in >> std::ws && in.peek() == '[') { // Edge properties in >> expect("[") >> ep >> Ignore(']'); assert(in); } edge_descriptor e; bool found; boost::tie(e, found) = edge(u, v, g); if (found) { // Parallel edge edge_property_type& ref = g[e]; ref = betterEP(ref, ep); } else add_edge(u, v, ep, g); } } else { std::cerr << "error: Expected `[' or `->' and saw `" << c << "'.\n"; exit(EXIT_FAILURE); } if (in >> std::ws && in.peek() == ';') in.get(); } if (in.fail()) in.clear(); // Check for the closing brace. in >> expect("}") >> std::ws; assert(in.eof()); assert(num_vertices(g) > 0); return in; } #endif