I have a network of around 1000 nodes. I have set stabilize:true and zoomExtentOnStabilize: true. The nodes are being added from JSON using vis.network.gephiParser.parseGephi() function. When I tried to plot this graph it never stabilizes even after hours of letting it idle. But then smaller number of nodes stabilize in reasonable time. What am I missing here. Is there any way to stabilize big graphs. I even tried setting the number of iterations to stabilize to 1000 and even higher. Thanks in advance for the help.
P.S.:The coordinates of the nodes are not available from JSON. The graph is redrawn based on the user input.
EDIT 1:
The JSON data being plotted is available at http://pastebin.com/raw.php?i=Mzy4ncxw. I couldn't make a reproducible example at jsbin because of CORS error.
The JavaScript code is:
message = JSON.parse(json_data); // json_data is sent from R server.
var nodes = new vis.DataSet();
var edges = new vis.DataSet();
var container = document.getElementById("div_graph");
var data = {
nodes: nodes,
edges: edges
};
var options = {
tooltip: {
delay: 50,
fontColor: "black",
fontSize: 14,
fontFace: "verdana",
color: {
border: "#666",
background: "#FFFFC6"
}
},
clustering: {
enabled: clusteringOn,
clusterEdgeThreshold: 50
},
hideEdgesOnDrag: true,
stabilize: true,
zoomExtentOnStabilize: true,
navigation: true,
keyboard: true,
edges: {
inheritColor: "to"
}
};
var network = new vis.Network(container, data, options);
nodes.clear();
edges.clear();
var parsed = vis.network.gephiParser.parseGephi(message);
nodes.add(parsed.nodes);
edges.add(parsed.edges);
network.redraw();
I'm the developer of the network module of visjs. we have used it to stabilize much larger sets than 1000 nodes. I can't really say what's going wrong here based on the information you supply. I'd like to invite you to make an issue on our github page. We try to collect all questions there. Can you share the code you use or your data (labels scrambled for anonymity ofcourse).
If I were to guess, a 1000 node system would stabilize with about 3000 iterations. If you are using dynamic smooth curves this increases greatly as support nodes are added to position the curves. I have used 15000 iterations for a 3000 node and 25000 edge system and even then it is not finished but I stop the simulation at that point regardless.
When you say redrawn on user input, is the data reloaded or redrawn in the sense that you see the dragging or zooming (similar to the redraw function)?
~ Alex
EDIT:
Based on your data I encoutered a few problems.
First, it seems you do not allow the nodes to move but also do not supply their positions, leading to an infinite recursion in the quadtree building process. I'll make the gephiParser more robust for this in the future.
See here for settings of the gephi parser: http://visjs.org/docs/network.html#Gephi_import
Secondly, You use dynamic smooth curves and a lot of interconnected nodes. Each smooth curve has an invisible support node that helps the positioning. This makes your system unstable (look at it with stabilize of to see the behaviour). In the v4 version you can set your own timestep to rectify this, but alternatively you can change your physics settings. Try the configurePhysics option and see if that helps. You can still use static smooth curves for aesthetic purposes.
To wrap up, I could get your system to stabilize with static smooth curves in about 3000 iterations, taking about a minute. I disabled clustering in your options. I'd recommend you wait for the 4.0 release to use clustering as it will be much much more powerful.
EDIT 2:
Here is a JSBin showing a working stabilization with your code and data (although modified)
http://jsbin.com/tiwijixoha/5/edit?html,output
So if you ment that it does not stabilize in the sense that it does not hide itself and only shows when it is ready instead of never reaching a stabilized state, then the problem is that stabilization is only done with a setData(), not with a dataset update.
In this jsbin I have also changed your edges and altered the physics to make it stable. You can play around with it a bit more if you're unhappy with it.
I'm using arbor js to create diagrams using its force-based alorithm.
I would like to be able to save the x,y system coordinates of the nodes after the total energy has got below a certain point, so that I can load them back in when accessing the graph, to avoid having to re-process all the energy from scratch.
I have had two problems doing this:
sys.energy().sum always returns NaN
as an alternative I decided to use setTimeout to save the graph node positions after a given period of time has elapsed
While I have been able to save the nodes x,y system coordinates to DB, when I try to load the data into the graph (using sys.merge or sys.addNode) with saved x y coordinates, the graph fails to display, and an 'out of memory' message appears in the console log.
Here is an example of data with node x,y system coordinates that were saved, and which causes arbor js to crash which loading:
{"nodes":{"0":{"edgeCount":0,"x":13.11901,"y":14.89151,"id":0,"name":"Global"},"23":
{"edgeCount":1,"x":18.08981,"y":-0.8355745,"id":23,"name":"Aristotle"},"26":
{"edgeCount":1,"x":5.688836,"y":14.86863,"id":26,"name":"Socrates"},"27":
{"edgeCount":1,"x":14.84461,"y":-1.687457,"id":27,"name":"Christianity"},"34":
{"edgeCount":1,"x":-2.265221,"y":13.59168,"id":34,"name":"Maths"},"91":
{"edgeCount":11,"x":5.868572,"y":-1.315289,"id":91,"name":"Plato"},"92":
{"edgeCount":4,"x":-3.14131,"y":8.81194,"id":92,"name":"Virtue"},"127":
{"edgeCount":1,"x":-3.308347,"y":8.463552,"id":127,"name":"Poetry"},"131":
{"edgeCount":1,"x":7.605158,"y":-3.951363,"id":131,"name":"Wisdom"},"147":
{"edgeCount":1,"x":6.195698,"y":-4.572639,"id":147,"name":"Person"},"149":
{"edgeCount":1,"x":2.10395,"y":-2.390886,"id":149,"name":"Republic"},"171":
{"edgeCount":1,"x":3.359434,"y":-3.996424,"id":171,"name":"Justice"},"172":
{"edgeCount":1,"x":-0.2544371,"y":-4.218832,"id":172,"name":"Temperance"},"173":
{"edgeCount":1,"x":-8.773163,"y":2.587845,"id":173,"name":"Courage"},"178":
{"edgeCount":1,"x":-2.380451,"y":-5.787674,"id":178,"name":"Schopenhauer"},"194":
{"edgeCount":2,"x":-7.747643,"y":-1.653015,"id":194,"name":"Beauty"},"195":
{"edgeCount":1,"x":-10.45985,"y":-2.670299,"id":195,"name":"Objective"},"196":
{"edgeCount":1,"x":-10.64573,"y":-6.874766,"id":196,"name":"Truth"},"219":
{"edgeCount":1,"x":-6.22574,"y":-7.565969,"id":219,"name":"Theory of forms"},"221":
{"edgeCount":1,"x":-8.314561,"y":-7.570002,"id":221,"name":"Platinus"},"245":
{"edgeCount":0,"x":-13.20351,"y":-8.421284,"id":245,"name":"Diagram"},"254":
{"edgeCount":1,"x":-13.54734,"y":-7.7437,"id":254,"name":"Green"}},
"edges":{"23":{"91":{"context":{"id":0,"name":"Global"},"source":
{"id":23,"name":"Aristotle"},"predicate":{"id":21,"name":"studied with"},"target":
{"id":91,"name":"Plato"}}},"26":{"91":{"context":{"id":0,"name":"Global"},"source":
{"id":26,"name":"Socrates"},"predicate":{"id":2,"name":"inspires"},"target":
{"id":91,"name":"Plato"}}},"91":{"149":{"context":{"id":0,"name":"Global"},"source":
{"id":91,"name":"Plato"},"predicate":{"id":1,"name":"writes"},"target":
{"id":149,"name":"Republic"}},"219":{"context":{"id":0,"name":"Global"},"source":
{"id":91,"name":"Plato"},"predicate":{"id":1,"name":"writes"},"target":{"id":219,"name":"Theory of forms"}},"27":{"context":{"id":0,"name":"Global"},"source":{"id":91,"name":"Plato"},"predicate":
{"id":3,"name":"influences"},"target":{"id":27,"name":"Christianity"}},"178":{"context":
{"id":0,"name":"Global"},"source":{"id":91,"name":"Plato"},"predicate":
{"id":3,"name":"influences"},"target":{"id":178,"name":"Schopenhauer"}},"221":{"context":
{"id":0,"name":"Global"},"source":{"id":91,"name":"Plato"},"predicate":
{"id":3,"name":"influences"},"target":{"id":221,"name":"Platinus"}},"254":{"context":
{"id":245,"name":"Diagram"},"source":{"id":91,"name":"Plato"},"predicate":
{"id":28,"name":"is"},"target":{"id":254,"name":"Green"}},"34":{"context":
{"id":0,"name":"Global"},"source":{"id":91,"name":"Plato"},"predicate":{"id":33,"name":"is associated with"},"target":{"id":34,"name":"Maths"}},"127":{"context":
{"id":0,"name":"Global"},"source":{"id":91,"name":"Plato"},"predicate":{"id":47,"name":"is obsessed with"},"target":{"id":127,"name":"Poetry"}},"147":{"context":
{"id":0,"name":"Global"},"source":{"id":91,"name":"Plato"},"predicate":{"id":56,"name":"is type of"},"target":{"id":147,"name":"Person"}}},"92":{"131":{"context":{"id":91,"name":"Plato"},"source":
{"id":92,"name":"Virtue"},"predicate":{"id":28,"name":"is"},"target":
{"id":131,"name":"Wisdom"}},"171":{"context":{"id":91,"name":"Plato"},"source":
{"id":92,"name":"Virtue"},"predicate":{"id":28,"name":"is"},"target":
{"id":171,"name":"Justice"}},"172":{"context":{"id":91,"name":"Plato"},"source":
{"id":92,"name":"Virtue"},"predicate":{"id":28,"name":"is"},"target":
{"id":172,"name":"Temperance"}},"173":{"context":{"id":91,"name":"Plato"},"source":
{"id":92,"name":"Virtue"},"predicate":{"id":28,"name":"is"},"target":
{"id":173,"name":"Courage"}}},"194":{"195":{"context":{"id":91,"name":"Plato"},"source":
{"id":194,"name":"Beauty"},"predicate":{"id":28,"name":"is"},"target":
{"id":195,"name":"Objective"}},"196":{"context":{"id":91,"name":"Plato"},"source":
{"id":194,"name":"Beauty"},"predicate":{"id":33,"name":"is associated with"},"target":
{"id":196,"name":"Truth"}}}}}
I can find no examples of graphs where the node x,y coordinates are in the input data.
Looking at https://github.com/samizdatco/arbor/blob/master/src/physics/system.js#L83 it seems that it should be alright to include x and y value in the data dictionary. I'm not really sure from your example how you pass the data to the methods. Maybe try just adding a few of the nodes and see where they are placed. I have the same problem with the energy being NaN. Probably using a debugger will help.