Extracting Layers and Subgraph Clusters from Graphviz with gvpr
Asked Answered
O

1

3

I have a large Graphviz file where I have put different nodes and edges onto different layers. A number of nodes are grouped into a subgraph cluster.

This makes it easy to focus on the particular part of the graph that is important. However I would now like to extract each layer into its own DOT file automatically.

I've been using gvpr -i 'N[layer=="(*a*)"]' source.gv > a.gv, which achieves what I want, by extracting the nodes and edges, but it fails to extract the subgraph, so I lose the context of the nodes.

For example, with the source graph:

digraph {
    layers = "a:b";
    layerselect = "";

    subgraph cluster_alpha {
        label = "Alpha";
        a, b, c [layer = "a"];
    }

    subgraph cluster_beta {
        label = "Beta";
        d, e, f [layer = "b"];
    }

    g [layer = "a"];
    h [layer = "b"];

    g -> a [layer = "a"];
    h -> e [layer = "b"]
}

Running gvpr -i 'N[layer=="(*a*)"]' source.gv > a.gv results in the following output:

digraph gvpr_result {
    graph [layers="a:b:c",
        layerselect=""
    ];
    a    [layer=a];
    b    [layer=a];
    c    [layer=a];
    g    [layer=a];
    g -> a   [layer=a];
}

If you compare the output you will see that the box around nodes "a", "b", and "c" and the label "Alpha" is missing.

Do you have any suggestions on how I can use gvpr to also output the subgraph clusters, or some other strategy to output the nodes, edges, and subgraphs of a given layer to a DOT file?

Ottillia answered 22/6, 2018 at 6:35 Comment(0)
L
4

What you want needs a bit more code. Call this file source.gvpr:

BEG_G
 {
  int i;
  int found;
  graph_t subgraphs[int];
  graph_t subgraph;
  subgraph = fstsubg($);
  i = 0;
  while (subgraph != NULL)
   {
    if (substr(subgraph.name, 0, 1) != "%")
     {
      subgraphs[i++] = subgraph;
     }
    subgraph = nxtsubg(subgraph);
   }
 }

N[layer=="(*a*)"]
 {
  found = 0;
  for (i = 0; i < #subgraphs; ++i)
   {
    if (isSubnode(subgraphs[i], $))
     {
      graph_t sg = subg($T, subgraphs[i].name);
      copyA(subgraphs[i], sg);
      subnode(sg, $);
      ++found;
      break;
     }
   }
  if (found  == 0)
   {
    node_t newnode = node($T, $.name);
    copyA($, newnode);
   }
 }

E[layer=="(*a*)"]

Run it with:

gvpr -f source.gvpr source.gv -o a.gv

The result will hopefully be what you wanted:

digraph gvpr_result {
  graph [layers="a:b",
    layerselect=""
  ];
  subgraph cluster_alpha {
    graph [label=Alpha,
      layers="a:b"
    ];
    a    [layer=a];
    b    [layer=a];
    c    [layer=a];
  }
  g  [layer=a];
  g -> a   [layer=a];
}

I am working on a version for myself that allows the selection of wanted layers via command line arguments (-a) of gvpr. Also it looks like a separate layer is required for edges that connect nodes of different layers if you want them to vanish when only one of such layers is chosen.

Lippi answered 9/8, 2018 at 11:51 Comment(1)
Did you get the CLI-enabled version working?Atomism

© 2022 - 2024 — McMap. All rights reserved.