-
Notifications
You must be signed in to change notification settings - Fork 1
Drawing improvements #89
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| import unittest | ||
|
|
||
| import networkx as nx | ||
| import numpy as np | ||
| from cereeberus.data import ex_reebgraphs as ex_rg | ||
| from cereeberus.draw.layout import reeb_x_layout | ||
|
|
||
|
|
||
| class TestDrawLayout(unittest.TestCase): | ||
| def test_reeb_x_layout_returns_finite_x_for_all_nodes(self): | ||
| R = ex_rg.torus(multigraph=False, seed=0) | ||
|
|
||
| x_positions = reeb_x_layout(R, R.f, seed=17, repulsion=0.8) | ||
|
|
||
| self.assertEqual(set(x_positions.keys()), set(R.nodes)) | ||
| for v in R.nodes: | ||
| self.assertTrue(np.isfinite(x_positions[v])) | ||
| self.assertLessEqual(x_positions[v], 1.0 + 1e-9) | ||
| self.assertGreaterEqual(x_positions[v], -1.0 - 1e-9) | ||
|
|
||
| def test_reeb_x_layout_is_reproducible_with_seed(self): | ||
| R = ex_rg.torus(multigraph=False, seed=0) | ||
|
|
||
| x_a = reeb_x_layout(R, R.f, seed=123, repulsion=0.8) | ||
| x_b = reeb_x_layout(R, R.f, seed=123, repulsion=0.8) | ||
|
|
||
| for v in R.nodes: | ||
| self.assertAlmostEqual(x_a[v], x_b[v]) | ||
|
|
||
| def test_reeb_x_layout_empty_graph(self): | ||
| G = nx.Graph() | ||
| x_positions = reeb_x_layout(G, {}, seed=1, repulsion=0.5) | ||
| self.assertEqual(x_positions, {}) | ||
|
|
||
| def test_reeb_x_layout_same_height_isolated_nodes(self): | ||
| # Regression test: no edges + same-height nodes should not trigger | ||
| # unbounded optimisation drift. | ||
| G = nx.Graph() | ||
| nodes = ["u", "v", "w", "z"] | ||
| G.add_nodes_from(nodes) | ||
| f = {node: 0.0 for node in nodes} | ||
|
|
||
| x_positions = reeb_x_layout(G, f, seed=9, repulsion=1.0) | ||
|
|
||
| self.assertEqual(set(x_positions.keys()), set(nodes)) | ||
| for node in nodes: | ||
| self.assertTrue(np.isfinite(x_positions[node])) | ||
| self.assertLessEqual(x_positions[node], 1.0 + 1e-9) | ||
| self.assertGreaterEqual(x_positions[node], -1.0 - 1e-9) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,9 +1,12 @@ | ||||||
| import unittest | ||||||
| from cereeberus import ReebGraph, MapperGraph | ||||||
|
|
||||||
| import numpy as np | ||||||
| from cereeberus.data import ex_graphs as ex_g | ||||||
| from cereeberus.data import ex_reebgraphs as ex_rg | ||||||
| from cereeberus.data import ex_mappergraphs as ex_mg | ||||||
| import numpy as np | ||||||
| from cereeberus.data import ex_reebgraphs as ex_rg | ||||||
|
|
||||||
| from cereeberus import MapperGraph, ReebGraph | ||||||
|
|
||||||
|
|
||||||
| class TestMapperClass(unittest.TestCase): | ||||||
|
|
||||||
|
|
@@ -129,8 +132,19 @@ def test_dist_matrix(self): | |||||
| # Check the whole put together matrix | ||||||
| M = R.thickening_distance_matrix() | ||||||
| self.assertEqual(M[5][3,10], np.inf) | ||||||
|
|
||||||
| def test_set_pos_from_f_preserves_delta_scaled_y_values(self): | ||||||
| # Mapper layout should keep y = delta * f(v), with repulsion only affecting x. | ||||||
| MG = ex_mg.torus(delta=0.2, seed=11) | ||||||
| MG.set_pos_from_f(seed=5, repulsion=0.9) | ||||||
|
|
||||||
| self.assertEqual(set(MG.nodes), set(MG.pos_f.keys())) | ||||||
| for v in MG.nodes: | ||||||
| self.assertEqual(MG.pos_f[v][1], MG.delta * MG.f[v]) | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
| if __name__ == '__main__': | ||||||
| unittest.main() | ||||||
| if __name__ == '__main__': | ||||||
|
Comment on lines
+148
to
149
|
||||||
| unittest.main() | |
| if __name__ == '__main__': |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,8 +1,11 @@ | ||||||
| import unittest | ||||||
| from cereeberus import ReebGraph | ||||||
|
|
||||||
| from cereeberus.data import ex_graphs as ex_g | ||||||
| from cereeberus.data import ex_reebgraphs as ex_rg | ||||||
|
|
||||||
| from cereeberus import ReebGraph | ||||||
|
|
||||||
|
|
||||||
| class TestReebClass(unittest.TestCase): | ||||||
|
|
||||||
| def check_reeb(self, R): | ||||||
|
|
@@ -227,11 +230,22 @@ def test_matrices(self): | |||||
| B = R.boundary_matrix() | ||||||
| self.assertEqual(B.shape, (len(R.nodes), len(R.edges))) | ||||||
|
|
||||||
| def test_set_pos_from_f_preserves_y_function_values(self): | ||||||
| # The constrained layout updates x-coordinates only; y should remain f(v). | ||||||
| R = ex_rg.torus(multigraph=False) | ||||||
| R.set_pos_from_f(seed=3, repulsion=1.2) | ||||||
|
|
||||||
| self.assertEqual(set(R.nodes), set(R.pos_f.keys())) | ||||||
| for v in R.nodes: | ||||||
| self.assertEqual(R.pos_f[v][1], R.f[v]) | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
| if __name__ == '__main__': | ||||||
| unittest.main() | ||||||
| if __name__ == '__main__': | ||||||
|
Comment on lines
+249
to
250
|
||||||
| unittest.main() | |
| if __name__ == '__main__': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The module docstring at the top defines the layout energy without the new centering term, but the implementation now adds
center_weight * dot(x, x)(and bounds). Please update the documented energy expression/description so it matches the optimizer objective.