From f56c92a22bb3963cb68d557228f0cec52828be3b Mon Sep 17 00:00:00 2001 From: Stefan Hahmann Date: Mon, 19 May 2025 14:58:45 +0200 Subject: [PATCH] Fix stack overflow in case of loops in the graph In case of loops in the graph, more precisely, in the situation, when the last spot of a branch has an outgoing edge to itself, label spots systematically got to a stack overflow situation due to a recursion that does not finish. This commit adds conditions to leave the recursion and extends the unit test to proof, the fix is working --- .../LabelSpotsSystematically.java | 6 ++- .../LabelSpotsSystematicallyTest.java | 39 ++++++++++++------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/mastodon/mamut/tomancak/label_systematically/LabelSpotsSystematically.java b/src/main/java/org/mastodon/mamut/tomancak/label_systematically/LabelSpotsSystematically.java index abd6d20..ee84691 100644 --- a/src/main/java/org/mastodon/mamut/tomancak/label_systematically/LabelSpotsSystematically.java +++ b/src/main/java/org/mastodon/mamut/tomancak/label_systematically/LabelSpotsSystematically.java @@ -78,8 +78,10 @@ private static void renameDescendants( ModelGraph graph, Predicate filter, Spot child1 = edges.next().getTarget(ref2); Spot child2 = edges.next().getTarget(ref3); boolean b = correctOrder.test( branchEnd ); - renameDescendants(graph, filter, correctOrder, spot, child1, b ); - renameDescendants(graph, filter, correctOrder, spot, child2, !b ); + if ( !branchEnd.equals( child1 ) ) // NB: edge linking to itself. this normally should not happen but occurs in real data. + renameDescendants( graph, filter, correctOrder, spot, child1, b ); + if ( !branchEnd.equals( child2 ) ) // NB: edge linking to itself. this normally should not happen but occurs in real data. + renameDescendants( graph, filter, correctOrder, spot, child2, !b ); } finally { diff --git a/src/test/java/org/mastodon/mamut/tomancak/label_systematically/LabelSpotsSystematicallyTest.java b/src/test/java/org/mastodon/mamut/tomancak/label_systematically/LabelSpotsSystematicallyTest.java index 34d3e0d..2681630 100644 --- a/src/test/java/org/mastodon/mamut/tomancak/label_systematically/LabelSpotsSystematicallyTest.java +++ b/src/test/java/org/mastodon/mamut/tomancak/label_systematically/LabelSpotsSystematicallyTest.java @@ -83,20 +83,33 @@ private double[] array( double... values ) } @Test - public void testRenameCellsAsExternIntern() { + public void testRenameCellsAsExternIntern() + { ModelGraph graph = new ModelGraph(); - Spot a = addSpot(graph, "a", array(2, 2, 2)); - Spot a1 = addSpotAsDescendantOf(graph, "2", a, array(1, 2, 2)); // extern - Spot a2 = addSpotAsDescendantOf(graph, "1", a, array(3, 2, 2)); // intern - Spot center = addSpot(graph, "center", array(4, 2, 2)); - Spot b = addSpot(graph, "b", array(6, 2, 2)); - Spot b2 = addSpotAsDescendantOf(graph, "4", b, array(5, 2, 2)); // intern - Spot b1 = addSpotAsDescendantOf(graph, "3", b, array(7, 2, 2)); // extern - LabelSpotsSystematically.setLabelsBasedOnExternIntern( graph, Collections.singleton( center ), graph.vertices(), true, false); - assertEquals("a1", a1.getLabel()); - assertEquals("a2", a2.getLabel()); - assertEquals("b1", b1.getLabel()); - assertEquals("b2", b2.getLabel()); + Spot a = addSpot( graph, "a", array( 2, 2, 2 ) ); + Spot a1 = addSpotAsDescendantOf( graph, "2", a, array( 1, 2, 2 ) ); // extern + Spot a2 = addSpotAsDescendantOf( graph, "1", a, array( 3, 2, 2 ) ); // intern + Spot center = addSpot( graph, "center", array( 4, 2, 2 ) ); + Spot b = addSpot( graph, "b", array( 6, 2, 2 ) ); + Spot b2 = addSpotAsDescendantOf( graph, "4", b, array( 5, 2, 2 ) ); // intern + Spot b1 = addSpotAsDescendantOf( graph, "3", b, array( 7, 2, 2 ) ); // extern + Spot c = addSpot( graph, "c", array( 8, 2, 2 ) ); + Spot c2 = addSpotAsDescendantOf( graph, "5", c, array( 9, 2, 2 ) ); // intern + Spot c1 = addSpotAsDescendantOf( graph, "6", c, array( 10, 2, 2 ) ); // extern + Spot c12 = addSpotAsDescendantOf( graph, "7", c1, array( 11, 2, 2 ) ); // intern + Spot c11 = addSpotAsDescendantOf( graph, "8", c1, array( 12, 2, 2 ) ); // extern + Spot c21 = addSpotAsDescendantOf( graph, "9", c2, array( 13, 2, 2 ) ); + graph.addEdge( c2, c2 ).init(); // deliberately create a cycle to test the robustness of the algorithm + LabelSpotsSystematically.setLabelsBasedOnExternIntern( graph, Collections.singleton( center ), graph.vertices(), true, false ); + assertEquals( "a1", a1.getLabel() ); + assertEquals( "a2", a2.getLabel() ); + assertEquals( "b1", b1.getLabel() ); + assertEquals( "b2", b2.getLabel() ); + assertEquals( "c1", c1.getLabel() ); + assertEquals( "c2", c2.getLabel() ); + assertEquals( "c11", c11.getLabel() ); + assertEquals( "c12", c12.getLabel() ); + assertEquals( "c21", c21.getLabel() ); } // Handling: