Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new feature: visualization supports edge coloring (#1160)
* edge score plotting: general setup and cytoscape d * 3d plotly, custom color palette * add tests, wip 2d plotly * Add support 2D Plotly rendering with edge scores. * Use numpy arrays for edge tuple generation. * Detect arbitrary ordering of edge tuples for edge scores. * Add test for wrong inputs, fix missing dependencies on CI. * Add helper method _getEdgeScore + format file with black formatter. * Revise function for edgescore retrieval. * Remove break from testing loop. * CI: Add vizbridges packages for Python tests for coverage, Windows builds. * Python: Rewrite testVizNodePartition test to use deterministic partitions. --------- Co-authored-by: fabratu <fabbrandt@gmail.com>
- Loading branch information
Showing
5 changed files
with
741 additions
and
320 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import networkit as nk | ||
from networkit import vizbridges | ||
import unittest | ||
from collections import defaultdict | ||
|
||
|
||
class TestVizbridges(unittest.TestCase): | ||
def getSmallGraph(self, weighted=False, directed=False): | ||
G = nk.Graph(4, weighted, directed) | ||
G.addEdge(0, 1, 1.0) | ||
G.addEdge(0, 2, 2.0) | ||
G.addEdge(3, 1, 4.0) | ||
G.addEdge(3, 2, 5.0) | ||
G.addEdge(1, 2, 3.0) | ||
if directed: | ||
G.addEdge(2, 1, 6.0) | ||
|
||
return G | ||
|
||
def testVizNodeScores(self): | ||
for dim, directed, weighted in zip( | ||
vizbridges.Dimension, [True, False], [True, False] | ||
): | ||
with self.subTest(dim=dim, directed=directed, weighted=weighted): | ||
G = self.getSmallGraph(weighted, directed) | ||
vizbridges.widgetFromGraph( | ||
G, | ||
dimension=dim, | ||
nodeScores=list(range(G.numberOfNodes())), | ||
) | ||
|
||
def testVizNodePartition(self): | ||
for dim, directed, weighted in zip( | ||
vizbridges.Dimension, [True, False], [True, False] | ||
): | ||
with self.subTest(dim=dim, directed=directed, weighted=weighted): | ||
G = self.getSmallGraph(weighted, directed) | ||
partition = nk.Partition(G.numberOfNodes()) | ||
partition.allToSingletons() | ||
vizbridges.widgetFromGraph( | ||
G, | ||
dimension=dim, | ||
nodePartition=partition, | ||
) | ||
|
||
def testVizNodePalette(self): | ||
for dim, directed, weighted in zip( | ||
vizbridges.Dimension, [True, False], [True, False] | ||
): | ||
with self.subTest(dim=dim, directed=directed, weighted=weighted): | ||
G = self.getSmallGraph(weighted, directed) | ||
vizbridges.widgetFromGraph( | ||
G, | ||
dimension=dim, | ||
nodeScores=list(range(G.numberOfNodes())), | ||
nodePalette=[(i / 10, i / 10, i / 10) for i in range(4)], | ||
) | ||
|
||
def testVizShowIds(self): | ||
for dim, directed, weighted, show in zip( | ||
vizbridges.Dimension, [True, False], [True, False], [True, False] | ||
): | ||
with self.subTest(dim=dim, directed=directed, weighted=weighted, show=show): | ||
G = self.getSmallGraph(weighted, directed) | ||
vizbridges.widgetFromGraph( | ||
G, | ||
dimension=dim, | ||
nodeScores=list(range(G.numberOfNodes())), | ||
showIds=show, | ||
) | ||
|
||
def testVizCustomSize(self): | ||
for dim, directed, weighted in zip( | ||
vizbridges.Dimension, [True, False], [True, False] | ||
): | ||
with self.subTest(dim=dim, directed=directed, weighted=weighted): | ||
G = self.getSmallGraph(weighted, directed) | ||
vizbridges.widgetFromGraph( | ||
G, | ||
dimension=dim, | ||
nodeScores=list(range(G.numberOfNodes())), | ||
customSize=50, | ||
) | ||
|
||
def testVizEdgeScoresList(self): | ||
for dim, directed, weighted in zip( | ||
vizbridges.Dimension, [True, False], [True, False] | ||
): | ||
with self.subTest(dim=dim, directed=directed, weighted=weighted): | ||
G = self.getSmallGraph(weighted, directed) | ||
G.indexEdges() | ||
vizbridges.widgetFromGraph( | ||
G, | ||
dimension=dim, | ||
edgeScores=list(range(G.numberOfEdges())), | ||
) | ||
|
||
def testVizEdgeScoresDict(self): | ||
for dim, directed, weighted in zip( | ||
vizbridges.Dimension, [True, False], [True, False] | ||
): | ||
with self.subTest(dim=dim, directed=directed, weighted=weighted): | ||
G = self.getSmallGraph(weighted, directed) | ||
G.indexEdges() | ||
scores = {} | ||
for i, [u, v] in enumerate(G.iterEdges()): | ||
scores[u, v] = i | ||
vizbridges.widgetFromGraph( | ||
G, | ||
dimension=dim, | ||
edgeScores=scores, | ||
) | ||
|
||
def testVizEdgeScoresUndirectedReversed(self): | ||
for dim, weighted in zip( | ||
vizbridges.Dimension, [True, False] | ||
): | ||
with self.subTest(dim=dim, weighted=weighted): | ||
G = self.getSmallGraph(weighted, False) | ||
G.indexEdges() | ||
scores = {} | ||
for i, [u, v] in enumerate(G.iterEdges()): | ||
scores[v, u] = i | ||
vizbridges.widgetFromGraph( | ||
G, | ||
dimension=dim, | ||
edgeScores=scores, | ||
) | ||
|
||
def testVizEdgeScoresDefaultdict(self): | ||
for dim, directed, weighted in zip( | ||
vizbridges.Dimension, [True, False], [True, False] | ||
): | ||
with self.subTest(dim=dim, directed=directed, weighted=weighted): | ||
G = self.getSmallGraph(weighted, directed) | ||
G.indexEdges() | ||
scores = defaultdict(lambda: 0) | ||
for u, v in G.iterEdges(): | ||
scores[u, v] = 1 | ||
vizbridges.widgetFromGraph( | ||
G, | ||
dimension=dim, | ||
edgeScores=scores, | ||
) | ||
|
||
def testVizEdgePalette(self): | ||
for dim, directed, weighted in zip( | ||
vizbridges.Dimension, [True, False], [True, False] | ||
): | ||
with self.subTest(dim=dim, directed=directed, weighted=weighted): | ||
G = self.getSmallGraph(weighted, directed) | ||
G.indexEdges() | ||
vizbridges.widgetFromGraph( | ||
G, | ||
dimension=dim, | ||
edgeScores=list(range(G.numberOfEdges())), | ||
edgePalette=[(i / 10, i / 10, i / 10) for i in range(4)], | ||
) | ||
|
||
def testNodeScoreAndPartitionExclusive(self): | ||
G = self.getSmallGraph(False, False) | ||
partition = nk.community.ClusteringGenerator(G).makeRandomClustering(G, 3) | ||
with self.assertRaises(Exception): | ||
vizbridges.widgetFromGraph( | ||
G, nodeScores=list(range(G.numberOfNodes())), nodePalette=partition | ||
) | ||
|
||
def testCompleteNodeScores(self): | ||
G = self.getSmallGraph(False, False) | ||
with self.assertRaises(Exception): | ||
vizbridges.widgetFromGraph(G, nodeScores=list(range(G.numberOfNodes() - 1))) | ||
|
||
def testCompleteEdgeScores(self): | ||
G = self.getSmallGraph(False, False) | ||
with self.assertRaises(Exception): | ||
vizbridges.widgetFromGraph(G, edgeScores=list(range(G.numberOfEdges() - 1))) | ||
|
||
def testNoneInEdgeScores(self): | ||
G = self.getSmallGraph(False, False) | ||
scores = [None] * G.numberOfEdges() | ||
with self.assertRaises(Exception): | ||
vizbridges.widgetFromGraph(G, edgeScores=scores) | ||
|
||
|
||
if __name__ == "__main__": | ||
unittest.main() |
Oops, something went wrong.