I am using Cytoscape.js to visualize networks.
I am currently using the cola layout which works a treat when one network (with zero orphan nodes) is generated.
However if I add an additional network on screen that is unaffiliated to the first with zero connections, on visualization the two separate networks a re positioned miles apart.
I have to manually grab one of the networks as a cluster and drag it for ages until it is closer to the other network.
My assumption is there is a way to set the distance between two graphs manually however how can I do this?
As far as I know, Cola does not have a component-packing algorithm. That would conflict with its live-animated, n-body physics simulation. Components are naturally repelled from one another, unless there is a strong gravity force to the screen's centre.
Component packing is typically a separate step for force-directed layouts, so it would give a jittery result when coupled with live animation. You may have better luck with other force-directed layouts with different trade-offs, such as FCOSE.
Related
I am building a web app where the user can create a sort of bipartite graph like this one:
Sometimes the user would like to build a huge graph, for example a graph in which the topmost layer has 784 nodes, as in the next picture. My application can handle the computation, but the result is ugly and meaningless:
Do you have any idea for rendering a huge layer without just drawing all the nodes but, instead, summarising them with another, prettier representation?
Until now I have thought about putting all the nodes of a "huge" layer in an empty compound node, but of course then it is not possible to draw some edges (so the huge layer would seem as it were disconnected from the graph). Another solution would be to have all layers with more than 100 nodes have exactly 100 nodes, and put them inside a compound node with z-index greater than each node's z-index; but I haven't tried this yet.
If you have some other ideas, or if Cytoscape.js provides a way to summarise large graphs, please let me know.
Thank you.
you could group nodes when the amount in a layer exceeds a certain number (e.g. if you have 100 nodes, you combine them into groups of 25)
I'd do this by iterating over the nodes in the layer, making a new node N for each subgroup (inserting all relevant information needed), and then replacing any mention of the replaced nodes by N in all relevant edges (finding connected edges).
As I personally generate layouts/nodes in python before sending them to cytoscape for visualization, I'll refrain from posting a potentially ineffecient/incorrect javascript/cytoscape example :)
we're currently building a web application (AngularJS) which needs to draw directed acyclic graphs (up to 1000 nodes, up to 10000 edges) based on dynamically created data.
Since over a year I am looking for a library/tool which is calculating the required layout and drawing a graph which can be styled, is zoom and panable, interactive (e.g. highlight children on mouse over).
Graphviz is the tool which produces the best results but it's not really ready to be used on webservers (especially as I cannot guarantee the OS and don't want to).
I tried dagre and it's d3 rendering - and I like it very much, but it has two major drawbacks: 1) it doesn't really support ranking and clustering - which makes the output rather chaotic and 2) with the graphs getting bigger its performance is getting unacceptable.
Next thing which really looked convincing was cytoscape.js as the output looks very nice and it's rather fast in drawing even larger graphs (and allowing some performance tweaking). But its standard layouting (e.g. cose or breadthfirst) doesn't produce the output we're requireing.
From my current point of view a have two chances:
1) Create layout with dagre.js and drawing the result with cytoscape.js (layout: 'preset', using the calculated x and y for nodes from dagre layout). But 'compounds'/clusters are not supported that way.
2) Using [viz.js](https://github.com/mdaines/viz.js) (an emscripted Javascript version of Graphviz, again not really performing well in drawing the graphs) to calculate the result as output format plain and again using this result to draw it with cytoscape.js.
Now my question(s):
1) Do you have another idea how to achieve it?
2) Could you give me any hint on how to ideally link the chain if my ideas are correct?
(AngularJS -> REST Backend -> JSON to Frontend -> Restructure JSON for dagre or viz -> Calculate layout -> input result to cytoscape -> render in browser?!?) and is there a chance to do the layout calculation on my node.js frontend server and not the client itself (again due to performance)?
Any hint and idea is heaviley appreciated.
It sounds like you're dissatisfied with Dagre as a compound layout. That makes sense, because the author of Dagre did not implement compound support for it. Dagre is separate from Cytoscape.js but can be used by it. You'll note the author of Dagre has stated he will no longer update the library with new features from himself. Thus, your options are:
(1) Use another Cytoscape.js layout actually designed for compound nodes, like CoSE or Cola.
(2) Write your own layout for Cytoscape.js that meets your needs: http://js.cytoscape.org/#extensions/layouts
(3) Adapt Dagre to recognise compound nodes and make a pull request to the author: https://github.com/cpettitt/dagre Then the Cytoscape.js layout for Dagre can be updated to use the new Dagre APIs that you add.
Currently, compound graph layout is an open research area -- so you'll be hard pressed to find many layouts that support them at all in any library. Cytoscape.js has some compound supporting layouts, and you're free to fork them if you want different behaviour. Also note that the 2.5 branch has CoSE2 with an improved algorithm.
Cytoscape.js can use a dagre layout. You can look here in the cytoscape docs for more information, but you can just add your nodes and edges to the graph and then run the dagre layout. That way you don't have to position all of the nodes manually based on the position of nodes from the separate dagre.js.
I am working on a project where data points are visualized in the scatterplot using d3. Since it is a web application, the region is limited and a lot of points overlap. In total there are 20k points and I allow users zooming in with a brush (and its extent) on regions, but even when zoomed in there is still a huge overlap of points. An example of such a situation:
What are good approaches to still visualize underlying points, to enhance the view or perception of the points? I was thinking about maybe using transparency, but I do not know if that would do it.
It might be worthy to note that all points represent genes, so clustering them may not be very logical in terms of representation.
I would suggest trying d3's fisheye plug-in. It allows you to zoom and distort the scale with the mouse letting you zoom in on areas.
You can see an example of it used with a scatter/bubble chart lower on the page here: http://bost.ocks.org/mike/fisheye/
In addition, if you have overlap I would increase opacity, so you can see which points have lots of overlap vs. points that don't.
Here's an example graph with very clustered points that I created using both fisheye and opacity: http://crclayton.com/projects/fisheye/
It also allows you to hover over individual points to see a tooltip containing more details about them.
If the number of data points is of interest, then you could cluster the points (either on client/server side). You typically see this pattern if maps have too many markers (example cluster map).
Edit:
I am still not quite sure if I'm heading in the right direction. To visualize the quantity of points you could use a 3D visualization. Here is an idea taken from the Software Cities project:
You could basically render the position of the points on the plane and create vertical cylinders - the more points on the same spot, the higher the cylinder.
I need to use the algorithm of forces with a network, but that network is divided into parts.
For example, the vertices of the first part can not leave the part 1. The vertices of the part 2 need to be in part 2.
If there is a connection between a vertex from part 1 and a vertex from part 2, this connection will make these two vertices be near, however, will not let their parts.
This draft image illustrates the idea:
I need to do this for about 8 parts. Some parts are in the other, other parts are next to each other. And the network will be represented on these parts, each vertex in their respective part, however, the algorithm forces should try to pull the connected vertices themselves.
My solution was to create constraints using the "tick" function from d3.
To improve performance and avoid "locked" vertices on corners, I decided to use only circles.
For each node:
Make sure it is inside its region.
Make sure it is also not inside each of the other regions.
This ended up in lots of calculations for each node vs. each region. This is summed with the collision detection complexity. Yet, it handled networks with around a thousand nodes.
Details here:
Heberle, H., Carazzolle, M., Telles, G. et al. CellNetVis: a web tool for visualization of biological networks using force-directed layout constrained by cellular components. BMC Bioinformatics 18, 395 (2017). https://doi.org/10.1186/s12859-017-1787-5
Note for potential improvement: one of the most expensive calculations is the combo of checking over what elements a node is. For instance, if there was a native "browser's" function that giving a point x,y it returned the elements of an SVG that this point is over, it would make the visualization smoother and create "space" for more improvements. By the time I implemented it, I did not find such function.
The main question is pretty simple... I'm making a rather large Organization Chart (or genealogy) and I'm wondering whether I should be using SVG or Canvas.
Some of the requirements might sway the choice:
Must be able to display between 1 to 50,000 nodes/people
Needs to pan and zoom much like a Google/Bing map.
Need to be able to click on a node and pop open a dialog with extra details on the person.
I was initially leaning towards SVG, but I heard somewhere that it would have performance problems when drawing a large number of items. Also, it seems Canvas has better support in older browsers.
Thanks everyone for your input. The following is what I have come up with after exploring some of the advice given.
SVG: This route was very tempting due to its vectorized nature and its integration into the DOM. Sadly the performance of rendering +100k nodes killed this route.
Canvas: Performance wise this seemed to be a winner. However, at this point I will need to explore how to add onClick/onHover functionality to each of the rendered nodes.
Leaflet: This too is a winner. It takes care of a lot of concerns like the map-like navigation, performance and mobile ready. Though it isn't a solution as to 'how' to draw the org chart. However, what is nice about it is that you can feed it image tiles or canvas. Which gives us some choice.
So in the end it is likely that I'll be using image titles to begin with and then migrating to canvas... while keeping my eye on performance advancements in SVG.