Question

I'm trying to create a dynamically-updated Prefuse graph, where nodes are added and deleted regularly. I've been able to add nodes and edges fine, and then delete them, but I get exceptions when I try to add edges to the next set of nodes. Does anyone know of any pitfalls in removing nodes from a Prefuse graph? Or, does anyone know a better way to interact with a Prefuse graph dynamically?

(Note that the display is updating fine; at all times the display seems to match the contents of the graph. This isn't a dupe of Prefuse Toolkit: dynamically adding nodes and edges)

Code excerpts:

// Set up edge and node tables
Schema node_schema = new Schema();
Schema edge_schema = new Schema();
node_schema.addColumn("node_info", NodeInfo.class);
edge_schema.addColumn("source", int.class, 0);
edge_schema.addColumn("target", int.class, 0);
edge_schema.addColumn("edge_info", EdgeInfo.class);
graph_nodes = node_schema.instantiate();
graph_edges = edge_schema.instantiate();

...

// Set up visualization
graph = new Graph(graph_nodes, graph_edges, false);
vis_panel = new MyVisPanel(graph);

...

// Add nodes & edges
int new_node_1 = graph_nodes.addRow();
graph_nodes.set(new_node_1, "node_info", new NodeInfo());
int new_node_2 = graph_nodes.addRow();
graph_nodes.set(new_node_2, "node_info", new NodeInfo());
int new_edge = graph_edges.addRow();
graph_edges.set(new_edge, "target", new_node_1);
graph_edges.set(new_edge, "source", new_node_2);

... 

// Remove nodes
TupleSet nodes = graph.getNodes();
Iterator iter = nodes.tuples(my_predicate);
while(iter.hasNext())
{
    int row_to_delete = ((Tuple) iter.next()).getRow();
    if(graph.removeNode(row_to_delete))
    {
        System.out.println("Removed row " + row_to_delete);
    }
}

...

// Add nodes & edges again
int new_node_1 = graph_nodes.addRow();
graph_nodes.set(new_node_1, "node_info", new NodeInfo());
int new_node_2 = graph_nodes.addRow();
graph_nodes.set(new_node_2, "node_info", new NodeInfo());
int new_edge = graph_edges.addRow(); // <<-- Exception is thrown here
graph_edges.set(new_edge, "target", new_node_1);
graph_edges.set(new_edge, "source", new_node_2);

The exception I get is:

java.lang.IllegalArgumentException: Row index out of bounds: -1
    at prefuse.data.column.IntColumn.getInt(Unknown Source)
    at prefuse.data.Table.getInt(Unknown Source)
    at prefuse.data.Graph.updateDegrees(Unknown Source)
    at prefuse.data.Graph.updateDegrees(Unknown Source)
    at prefuse.data.Graph$Listener.tableChanged(Unknown Source)
    at prefuse.data.Table.fireTableEvent(Unknown Source)
    at prefuse.data.Table.addRow(Unknown Source)
    at my_pkg.addSomeNodesFunction(my_code.java:99)

I have not used the standard Graph.addNode() and addEdge() methods, because it seemed harder to set edge information that way. (if there's a better way to do this, let me know!) The delete is succeeding, in that graph.getNodeCount() and graph.getEdgeCount() return smaller numbers after deleting the nodes.

Any ideas?

Was it helpful?

Solution

After more investigation this appears to be a minor bug in prefuse. Calls to addEdge first initialize the source and target node numbers to 0, after which the graph tries to update its degree counts, which fails if node 0 does not exist. See bug report 3529747 on their SF page for more information.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top