Programming
Workshop

Spring 2006
course
navigation

Creating a simple Graph Visualization

This is a very basic example of using the prefuse toolkit.
Written in the following format : <?xml version="1.0" encoding="UTF-8"?> <graphml xmlns="http://graphml.graphdrawing.org/xmlns" > <graph edgedefault="undirected"> <key id="color" for="node" attr.name="color" attr.type="string"/> <key id="lame" for="node" attr.name="lame" attr.type="string"/> <node id="1"> <data key="color">green</data> <data key="lame">A</data> </node> <node id="2"> <data key="color">blue</data> <data key="lame">B</data> </node> <node id="3"> <data key="color">red</data> <data key="lame">C</data> </node> <node id="4"> <data key="color">turquoise</data> <data key="lame">D</data> </node> <node id="5"> <data key="color">Zarustra</data> <data key="lame">E</data> </node> <edge source="1" target="2"/> <edge source="2" target="3"/> <edge source="3" target="4"/> <edge source="4" target="1"/> <edge source="5" target="1"/> <edge source="5" target="2"/> <edge source="5" target="3"/> <edge source="5" target="4"/> </graph> </graphml> The file must be saved in the direct classpath of the script, otherwise it won't read and will spit out an exception error.

Imports

This changes constantly depending on what kinds of data or layout you're using. I've found the best strategy is to just use whatever you want and hunt down the specific imports after the fact.
import javax.swing.JFrame; import prefuse.Constants; import prefuse.Display; import prefuse.Visualization; import prefuse.action.ActionList; import prefuse.action.RepaintAction; import prefuse.action.layout.*; import prefuse.action.assignment.ColorAction; import prefuse.action.assignment.DataColorAction; import prefuse.action.layout.graph.*; import prefuse.activity.Activity; import prefuse.controls.DragControl; import prefuse.controls.PanControl; import prefuse.controls.ZoomControl; import prefuse.data.Graph; import prefuse.data.io.DataIOException; import prefuse.data.io.GraphMLReader; import prefuse.render.DefaultRendererFactory; import prefuse.render.LabelRenderer; import prefuse.util.ColorLib; import prefuse.visual.VisualItem; import prefuse.controls.WheelZoomControl;

Loading the Graph

You need to wrap the actual reading of the graph in a try/catch construct, since it throws an exception error if it's unable to read
public static void main(String argv[]){ Graph MyGraph = null; try { MyGraph = new GraphMLReader().readGraph("/Tester.xml"); } catch ( DataIOException e ) { System.err.println("Couldn't load the graph..."); System.exit(1); }

Build the Visualization Object

Now that we've got data, the next step is to build the visualization object, register our graph with the object, and set the edges (links) of the visualization to not react to user input.
Visualization MyViz = new Visualization(); MyViz.add("graph", MyGraph); MyViz.setInteractive("graph.edges", null, false);

Rendering

We'll just be using a simple label renderer for every node, so we can use the default render factory. Custom Renderer Factories can be created in order to adjust the look of the nodes based on search criteria.
LabelRenderer MyLabel = new LabelRenderer("lame"); MyLabel.setRoundedCorner(2, 2); MyViz.setRendererFactory(new DefaultRendererFactory(MyLabel));

Coloring

Creating the color rules is a bit of a process. First you need to create a color pallete which holds all the colors you want to use in the program. The order you create the colors is important for how they are assigned if you aren't using the ColorMap function:
int[] MyPalette = new int[] { ColorLib.rgb(0, 0, 255), //Blue ColorLib.rgb(0, 255, 0), //Green ColorLib.rgb(255, 0, 0), //Red ColorLib.rgb(0, 245, 255), //Turquoise ColorLib.rgb(255, 0, 255) //Purple };
Apply the coloring to the graph objects based on the alphabetic ordering of the color field of each node :
DataColorAction NodeFill = new DataColorAction( "graph.nodes", //The graph we're applying this to "color", //The Datafield used to determine color Constants.NOMINAL, //Define Datafield as Nominal (A Category) VisualItem.FILLCOLOR, //We're Filling the Node with Color MyPalette //We're using MyPalette for Color Values );

Now we have to define the colors of the text and the edges of each node:
//Set the text color to Black ColorAction text = new ColorAction( "graph.nodes", VisualItem.TEXTCOLOR, ColorLib.rgb(255, 255, 255) ); //Set the edge color to light gray ColorAction edges = new ColorAction( "graph.edges", VisualItem.STROKECOLOR, ColorLib.rgb(0, 0, 200) );

Action Lists

Now that everything else is set up, we need to build the action lists which will define the behavior of the visual elements within the display. I'm not sure if it's the correct way to go about it, but I've found that including a repaint action at the end of each Action List makes things run more smoothly.
First is the Coloring Action List:
ActionList Coloring = new ActionList(); Coloring.add(NodeFill); Coloring.add(text); Coloring.add(edges); Coloring.add(new RepaintAction());
Next up is the layout, because I'm using the force directed layout I'm setting up this Action List to continue running while the program is still executing:
ActionList DoLayout = new ActionList(Activity.INFINITY); DoLayout.add(new ForceDirectedLayout("graph", true)); DoLayout.add(new RepaintAction());
Last Actionlist is one to randomly reposition the nodes every second (just to keep things interesting).
ActionList Randomize = new ActionList(Activity.INFINITY, 1000); Randomize.add(new RandomLayout("graph")); Randomize.add(new RepaintAction());
Now that the action lists are built, they need to be registered with the visualization:
MyViz.putAction("Coloring", Coloring); MyViz.putAction("DoLayout", DoLayout); MyViz.putAction("Randomize", Randomize);

Building the Display

Now that we've got the visualization together, the display object needs to be built :
Display MyDisplay = new Display(MyViz); MyDisplay.setSize(300, 300);
Now the controller objects desired need to be created and registered with the display object :
MyDisplay.addControlListener(new DragControl()); //Dragging of Individual Nodes MyDisplay.addControlListener(new PanControl()); //Panning Controls MyDisplay.addControlListener(new ZoomControl()); //Right Click Zooming MyDisplay.addControlListener(new WheelZoomControl()); //Mouse Wheel Zooming

Building the JFrame

Now create a JFrame object to hold the display, configure it and set it visible.
JFrame MyFrame = new JFrame("Graph Visualization Demo"); MyFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); MyFrame.add(MyDisplay); MyFrame.pack(); MyFrame.setVisible(true);

Run Actionlists

All that's left is to execute the actionlists and start out the visualization :
MyViz.run("Coloring"); MyViz.run("DoLayout"); MyViz.run("Randomize"); }

attachments [paper clip]

     name last modified size
   simplegraph.jar Aug 31 2006 2:26 am 740kB [COD]simplegraph.java Aug 31 2006 2:26 am 3.71kB    tester.xml Aug 31 2006 2:26 am 1.09kB