From 48913a47e75561f0e3454e8a6c7600d998b7a84f Mon Sep 17 00:00:00 2001 From: lola Date: Tue, 17 Mar 2026 15:53:04 -0700 Subject: [PATCH 1/2] stabilize test_visibility_pruning --- tests/syntax/test_pruning.py | 42 +++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/tests/syntax/test_pruning.py b/tests/syntax/test_pruning.py index 6a0c693f6..483432ef1 100644 --- a/tests/syntax/test_pruning.py +++ b/tests/syntax/test_pruning.py @@ -1,10 +1,8 @@ -import math -import random - import pytest from scenic.core.errors import InconsistentScenarioError -from scenic.core.vectors import Vector +from scenic.core.regions import PointInRegionDistribution +from scenic.core.vectors import Vector, VectorOperatorDistribution from tests.utils import compileScenic, sampleEgo, sampleParamP @@ -174,11 +172,31 @@ def test_visibility_pruning(): We also want to confirm that we aren't pruning too much, i.e. placing the position in the viewRegion instead of at any point where the object intersects the view region. - Because of this, we want to see at least one sample where the position is outside - the viewRegion but the object intersects the viewRegion. The chance of this happening - per sample is ((1 / 2)**2), so by repeating the process 30 times we have - ~1e-19 chance of not getting a single point in this zone. + To check this deterministically, we verify that the pruned region still extends beyond + distance 1 from ego while remaining within distance 2, so the outer band where the + object intersects the view region is still available. """ + + def assert_pruned_region_reaches_outer_band(scenario): + foo = scenario.objects[1] + conditioned = foo.position._conditioned + + if isinstance(conditioned, PointInRegionDistribution): + base = conditioned.region + offset = Vector(0, 0, 0) + else: + assert isinstance(conditioned, VectorOperatorDistribution) + base = conditioned.object.region + offset = conditioned.operands[0] + + max_dist = max( + (Vector(x, y, base.z) + offset).distanceTo(Vector(0, 0, 0)) + for poly in base.polygons.geoms + for x, y in poly.exterior.coords + ) + assert max_dist <= 2 + 1e-6 + assert max_dist > 1 + 1e-6 + # requireVisible scenario = compileScenic( """ @@ -193,7 +211,7 @@ def test_visibility_pruning(): ) positions = [sampleParamP(scenario, maxIterations=100) for i in range(30)] assert all(pos.distanceTo(Vector(0, 0, 0)) <= 2 for pos in positions) - assert any(pos.distanceTo(Vector(0, 0, 0)) >= 1 for pos in positions) + assert_pruned_region_reaches_outer_band(scenario) # visible scenario = compileScenic( @@ -208,7 +226,7 @@ def test_visibility_pruning(): ) positions = [sampleParamP(scenario, maxIterations=100) for i in range(30)] assert all(pos.distanceTo(Vector(0, 0, 0)) <= 2 for pos in positions) - assert any(pos.distanceTo(Vector(0, 0, 0)) >= 1 for pos in positions) + assert_pruned_region_reaches_outer_band(scenario) # requireVisible with offset baseOffsetVal = 0.0001 @@ -226,7 +244,7 @@ def test_visibility_pruning(): ) positions = [sampleParamP(scenario, maxIterations=100) for i in range(30)] assert all(pos.distanceTo(Vector(0, 0, 0)) <= 2 for pos in positions) - assert any(pos.distanceTo(Vector(0, 0, 0)) >= 1 for pos in positions) + assert_pruned_region_reaches_outer_band(scenario) assert all(pos.z == -baseOffsetVal for pos in positions) # visible with offset @@ -243,7 +261,7 @@ def test_visibility_pruning(): ) positions = [sampleParamP(scenario, maxIterations=100) for i in range(30)] assert all(pos.distanceTo(Vector(0, 0, 0)) <= 2 for pos in positions) - assert any(pos.distanceTo(Vector(0, 0, 0)) >= 1 for pos in positions) + assert_pruned_region_reaches_outer_band(scenario) assert all(pos.z == -baseOffsetVal for pos in positions) From 009ccfcc46d17dd7fc1a8b8a8eecfc6d97086166 Mon Sep 17 00:00:00 2001 From: lola Date: Thu, 2 Apr 2026 13:45:21 -0700 Subject: [PATCH 2/2] update docstring for test_visibility_pruning --- tests/syntax/test_pruning.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/tests/syntax/test_pruning.py b/tests/syntax/test_pruning.py index 483432ef1..859772c44 100644 --- a/tests/syntax/test_pruning.py +++ b/tests/syntax/test_pruning.py @@ -162,19 +162,16 @@ def test_visibility_pruning(): """Test visibility pruning in general. The following scenarios are equivalent except for how they specify that foo - must be visible from ego. The size of the workspace and the visibleDistance - of ego are chosen such that without pruning the chance of sampling a valid - scene over 100 tries is 1-(1-(3.14*2**2)/(1e10**2))**100 = ~1e-18. - Assuming the approximately buffered volume of the viewRegion has a 50% chance of - rejecting (i.e. it is twice as large as the true buffered viewRegion, which testing - indicates in this case has about a 10% increase in volume for this case), the chance - of not finding a sample in 100 iterations is 1e-31. - - We also want to confirm that we aren't pruning too much, i.e. placing the position - in the viewRegion instead of at any point where the object intersects the view region. - To check this deterministically, we verify that the pruned region still extends beyond - distance 1 from ego while remaining within distance 2, so the outer band where the - object intersects the view region is still available. + must be visible from ego. Without visibility pruning, sampling a valid scene + would be extremely unlikely because the workspace is enormous compared to ego's + visible region. + + We check two things. First, sampled positions must remain within distance 2 of + ego, which is the maximum distance at which the spheroid can still intersect + ego's visible region. Second, to ensure pruning is not too aggressive, we check + the conditioned/pruned region directly and verify that it still extends beyond + distance 1 from ego, so the outer band where the object intersects the view + region is still available. """ def assert_pruned_region_reaches_outer_band(scenario):