In the current layout, root nodes are selected if they are either: a rum agent node or an unconnected node. This is incorrect since it should select all nodes which have no incoming edges (which includes unconnected nodes) Cytoscape has a selector to obtain nodes with no incoming edges nodes.roots(), however when used, there are some nodes that appear to have incoming edges in the result set of root nodes.

This is due to logic we added to de-duplicate symmetric edges and style one of them with bidirectional arrow indicators. Since this logic effectively removes an incoming edge, cytoscape identies it as a root node while it's styled as bidirectional. One solution is to hide one of the symmetric edges rather than omit it from the resulting graph, allowing cytoscape to effectively identify it as a non-root node.
In the current layout, root nodes are selected if they are either: a rum agent node or an unconnected node. This is incorrect since it should select all nodes which have no incoming edges (which includes unconnected nodes) Cytoscape has a selector to obtain nodes with no incoming edges
nodes.roots(), however when used, there are some nodes that appear to have incoming edges in the result set of root nodes.This is due to logic we added to de-duplicate symmetric edges and style one of them with bidirectional arrow indicators. Since this logic effectively removes an incoming edge, cytoscape identies it as a root node while it's styled as bidirectional. One solution is to hide one of the symmetric edges rather than omit it from the resulting graph, allowing cytoscape to effectively identify it as a non-root node.