Menu

Layout subgraphs with different algorithms

Help
2006-05-29
2013-05-29
  • Aaron Barsky

    Aaron Barsky - 2006-05-29

    I want to use different layout algorithms to layout different portions of my graph.  After layout, I want all nodes and edges to be visible.
                                                                                                           
    I have tried the following unsuccesful ways of doing this
                                                                                                           
    1.  Use a visibility filter
      I add a new VisibilityFilter(vis,"graph", (Predicate) prefuse.data.expression.parser.ExpressionParser.parse("[graphRegion]="+i) for each region.  After running each of the layouts I set everything to visible.  This works for ForceDirectedLayout and RandomLayout which iterate through Visible items, but not for other layouts such as RadialTreeLayout or CircleLayout which ignore the Visible attribute and iterate through the entire graph.
                                                                                                           
    2.  Add multiple visualizations to a display
      I could create a Graph and a Visualization for each subgraph, lay them out individually and then add all the Visualizations to a single display.  While this works, I cannot draw the edges between the various subgraphs.
                                                                                                           
    Does anyone have a good way of working with subgraphs?  I feel as if there should be some way to use the Predicate features for all layouts.

     
    • Björn Kruse

      Björn Kruse - 2006-05-30

      hi,

      1. have you tried to run your different Layouts just for a special group? For example use m_vis.addFocusGroup("firstGroup"); ... m_vis.getFocusGroup("firstGroup").addTuple(item)
      to build your FocusGroups (also called secondary groups).
      Later when creating your Layouts use new XYLayout("firstGroup"). The layout should just consider the items contained in the group "firstGroup"...
      I'm doing this too and it works fine. A nice sideeffect: If you have this FocusGroups, its very easy to assign different renderers, colors, etc. to each FocusGroup.

      2. Using this approach you better add multiple graphs to one visualization, using a different name each time you add a graph to the visualization. But again, you can't have edges between nodes of different graphs in a straightforward way.

      greetz Björn

       
    • Aaron Barsky

      Aaron Barsky - 2006-05-30

      Thanks Bjoern,
        I should have mentioned that this was the first method I tried.  I'm intrigued that it works for you, because it doesn't work for me.  I think the problem ss that layouts like ForceDirectedLayout are expecting a composite tuple set with a node and edge subset, wheras addFocusGroup just creates a defaultTupleSet.

        Here's a small example where I tried to layout half the graph with ForceDirectedLayout.  Nothing happens at all when I pass in the focus group, but of course it lays out fine when I pass in the full graph.

      import javax.swing.JFrame;
      import prefuse.Display;
      import prefuse.Visualization;
      import prefuse.action.ActionList;
      import prefuse.action.RepaintAction;
      import prefuse.action.assignment.ColorAction;
      import prefuse.action.layout.graph.ForceDirectedLayout;
      import prefuse.activity.Activity;
      import prefuse.controls.DragControl;
      import prefuse.controls.PanControl;
      import prefuse.data.Graph;
      import prefuse.data.Table;
      import prefuse.data.tuple.TupleSet;
      import prefuse.render.DefaultRendererFactory;
      import prefuse.util.ColorLib;
      import prefuse.visual.VisualItem;

      public class Example {

          public static void main(String[] argv) {
             
              Table nodes = new Table ();
              for (int i=0; i < 10; i++){
                  nodes.addRow();
              }
             
              Table edges = new Table ();
              edges.addColumn (Graph.DEFAULT_SOURCE_KEY, int.class);
              edges.addColumn (Graph.DEFAULT_TARGET_KEY, int.class);
              for (int i=0; i <9; i++){
                  int row =edges.addRow();
                  edges.setInt (row,Graph.DEFAULT_SOURCE_KEY, i);
                  edges.setInt (row, Graph.DEFAULT_TARGET_KEY, i+1);
              }
              Graph graph = new Graph(nodes,edges, false);
             
              Visualization vis = new Visualization();
              vis.addGraph("graph", graph);
              vis.addFocusGroup("subgraph");
              TupleSet subgraph = vis.getFocusGroup("subgraph");
           
              for (int i=0; i < 5; i++)
                      subgraph.addTuple( nodes.getTuple(i));
             
              for (int i=0; i < 4; i++)
                  subgraph.addTuple(edges.getTuple(i));
             
              vis.setRendererFactory(new DefaultRendererFactory());
              Display d = new Display(vis);
              d.setSize(720, 500);
              d.addControlListener(new DragControl());
              d.addControlListener(new PanControl());
             
              ColorAction fill = new ColorAction ("graph.nodes", VisualItem.FILLCOLOR, ColorLib.color(ColorLib.getColor(0,0,255,255)));
              ColorAction edgecolor = new ColorAction("graph.edges", VisualItem.STROKECOLOR, ColorLib.gray(200));
              ColorAction nStroke = new ColorAction("graph.nodes", VisualItem.STROKECOLOR,ColorLib.gray(100));
            
              ActionList color = new ActionList();
              color.add(nStroke);
              color.add(edgecolor);
              color.add(fill);
             
              ActionList layout = new ActionList(Activity.INFINITY);
              //Everything works fine...
              //layout.add (new ForceDirectedLayout("graph"));
             
              //Nothing happens
              layout.add (new ForceDirectedLayout("subgraph"));
              layout.add(new RepaintAction());
              vis.putAction("color", color);
              vis.putAction("layout", layout);

              JFrame frame = new JFrame("prefuse example");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.add(d);
              frame.pack();          
              frame.setVisible(true);
              vis.run("color");
              vis.run("layout");
          }   
      }

      I would love to see some sample code where you ran a layout on a focus group!  Thanks for the help,

      Aaron

       
      • Björn Kruse

        Björn Kruse - 2006-05-30

        I haven't had the time yet to test your code, but as ForceDirectedLayout states:      * @param group the data group to layout. Must resolve to a Graph instance.

        Have you tried it with a simpler layout, e.g. CircleLayout or RandomLayout? They should be able to handle FocusGroups.
        btw: its easy to write your own layout! Simply extend Layout and provide your own x/y assignments in the "run" method.

        If you really need ForceDirectedLayout, you can probably hack it by always doing filtered iteration over the graph, instead of iterating over all items. But anyhow, I don't know how to handle the edge-issue :-(

        greetz
        Björn

         
      • Jeffrey Heer

        Jeffrey Heer - 2006-06-12

        One trick to try is to use the "setDataGroups" method for ForceDirectedLayout to pass in the node and edge groups directly. That way you can use your own specialized groups as input to the layout, rather than a group backed by a graph instance.

        -jeff

         
  • Anonymous

    Anonymous - 2009-12-10

    I am wondering the same thing.  The fact that three and a half years have gone by with nobody responding to your query fills me with doubt, though.

     

Log in to post a comment.