From 247bef7ff0021f834818ef67984b9323ec20d0d5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 18:09:59 +0000 Subject: [PATCH 1/4] Initial plan From f349fd10a75c5d5f3d802b264d31b1750140d3b8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 18:19:05 +0000 Subject: [PATCH 2/4] Fix vessel structure generation at boundaries Co-authored-by: jgroehl <7871475+jgroehl@users.noreply.github.com> --- .../structure_library/VesselStructure.py | 7 ++- .../structure_tests/test_vesseltree.py | 53 +++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/simpa/utils/libraries/structure_library/VesselStructure.py b/simpa/utils/libraries/structure_library/VesselStructure.py index a8c34771..f726eb9a 100644 --- a/simpa/utils/libraries/structure_library/VesselStructure.py +++ b/simpa/utils/libraries/structure_library/VesselStructure.py @@ -67,7 +67,7 @@ def calculate_vessel_samples(self, position, direction, bifurcation_length, radi radius_array = [radius] samples = 0 - while torch.all(position < torch.tensor(volume_dimensions).to(self.torch_device)) and torch.all(0 <= position): + while True: if samples >= bifurcation_length: vessel_branch_positions1 = position vessel_branch_positions2 = position @@ -101,6 +101,11 @@ def calculate_vessel_samples(self, position, direction, bifurcation_length, radi break position = torch.add(position, direction) + + # Check if the new position is within bounds before adding it + if not (torch.all(position < torch.tensor(volume_dimensions).to(self.torch_device)) and torch.all(0 <= position)): + break + position_array.append(position) radius_array.append(np.random.uniform(-1, 1) * radius_variation + radius) diff --git a/simpa_tests/automatic_tests/structure_tests/test_vesseltree.py b/simpa_tests/automatic_tests/structure_tests/test_vesseltree.py index 17958b81..e51ec8b2 100644 --- a/simpa_tests/automatic_tests/structure_tests/test_vesseltree.py +++ b/simpa_tests/automatic_tests/structure_tests/test_vesseltree.py @@ -113,3 +113,56 @@ def test_vessel_tree_geometrical_volume(self): assert 0 <= value <= 1 self.assertTrue(np.sum(ts.geometrical_volume) > 0) + + def test_vessel_starting_at_boundary(self): + """ + Test that vessels starting exactly at a tissue boundary are created correctly. + This is a regression test for the issue where vessels starting at boundaries + (e.g., y=16 for a 16mm volume) would not create proper tube structures. + """ + # Create settings for a vessel starting at the Y boundary + self.global_settings[Tags.SPACING_MM] = 0.5 + self.global_settings[Tags.DIM_VOLUME_X_MM] = 16 + self.global_settings[Tags.DIM_VOLUME_Y_MM] = 16 + self.global_settings[Tags.DIM_VOLUME_Z_MM] = 10 + + # Vessel starting exactly at boundary (y=16) + vessel_settings_boundary = Settings() + vessel_settings_boundary[Tags.STRUCTURE_START_MM] = [10, 16, 0.2] + vessel_settings_boundary[Tags.STRUCTURE_DIRECTION] = [-1, -1, 0.0] + vessel_settings_boundary[Tags.STRUCTURE_RADIUS_MM] = 2.0 + vessel_settings_boundary[Tags.STRUCTURE_CURVATURE_FACTOR] = 0.0 + vessel_settings_boundary[Tags.STRUCTURE_RADIUS_VARIATION_FACTOR] = 1.0 + vessel_settings_boundary[Tags.STRUCTURE_BIFURCATION_LENGTH_MM] = 1000.0 + vessel_settings_boundary[Tags.MOLECULE_COMPOSITION] = TissueLibrary.muscle() + vessel_settings_boundary[Tags.CONSIDER_PARTIAL_VOLUME] = True + vessel_settings_boundary[Tags.ADHERE_TO_DEFORMATION] = False + + # Vessel starting just inside boundary (y=15.99) + vessel_settings_inside = Settings() + vessel_settings_inside[Tags.STRUCTURE_START_MM] = [10, 15.99, 0.2] + vessel_settings_inside[Tags.STRUCTURE_DIRECTION] = [-1, -1, 0.0] + vessel_settings_inside[Tags.STRUCTURE_RADIUS_MM] = 2.0 + vessel_settings_inside[Tags.STRUCTURE_CURVATURE_FACTOR] = 0.0 + vessel_settings_inside[Tags.STRUCTURE_RADIUS_VARIATION_FACTOR] = 1.0 + vessel_settings_inside[Tags.STRUCTURE_BIFURCATION_LENGTH_MM] = 1000.0 + vessel_settings_inside[Tags.MOLECULE_COMPOSITION] = TissueLibrary.muscle() + vessel_settings_inside[Tags.CONSIDER_PARTIAL_VOLUME] = True + vessel_settings_inside[Tags.ADHERE_TO_DEFORMATION] = False + + vessel_boundary = VesselStructure(self.global_settings, vessel_settings_boundary) + vessel_inside = VesselStructure(self.global_settings, vessel_settings_inside) + + # Both vessels should have similar volumes (at least 80% similarity) + # The slight difference is due to randomness in vessel generation + volume_boundary = np.sum(vessel_boundary.geometrical_volume) + volume_inside = np.sum(vessel_inside.geometrical_volume) + + # Ensure both vessels have substantial volume + self.assertGreater(volume_boundary, 100, "Vessel at boundary should have substantial volume") + self.assertGreater(volume_inside, 100, "Vessel inside should have substantial volume") + + # Check that they are similar in size (within 20% tolerance) + ratio = volume_boundary / volume_inside + self.assertGreater(ratio, 0.8, f"Vessel at boundary should be at least 80% of inside vessel size, got {ratio:.2%}") + self.assertLess(ratio, 1.2, f"Vessel at boundary should be at most 120% of inside vessel size, got {ratio:.2%}") From 80d02143746d436397aefab94086e1e1a57fb8bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 18:20:22 +0000 Subject: [PATCH 3/4] Apply autopep8 formatting fixes Co-authored-by: jgroehl <7871475+jgroehl@users.noreply.github.com> --- simpa/utils/libraries/structure_library/VesselStructure.py | 4 ++-- .../automatic_tests/structure_tests/test_vesseltree.py | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/simpa/utils/libraries/structure_library/VesselStructure.py b/simpa/utils/libraries/structure_library/VesselStructure.py index f726eb9a..df2247a7 100644 --- a/simpa/utils/libraries/structure_library/VesselStructure.py +++ b/simpa/utils/libraries/structure_library/VesselStructure.py @@ -101,11 +101,11 @@ def calculate_vessel_samples(self, position, direction, bifurcation_length, radi break position = torch.add(position, direction) - + # Check if the new position is within bounds before adding it if not (torch.all(position < torch.tensor(volume_dimensions).to(self.torch_device)) and torch.all(0 <= position)): break - + position_array.append(position) radius_array.append(np.random.uniform(-1, 1) * radius_variation + radius) diff --git a/simpa_tests/automatic_tests/structure_tests/test_vesseltree.py b/simpa_tests/automatic_tests/structure_tests/test_vesseltree.py index e51ec8b2..c5f17d30 100644 --- a/simpa_tests/automatic_tests/structure_tests/test_vesseltree.py +++ b/simpa_tests/automatic_tests/structure_tests/test_vesseltree.py @@ -157,12 +157,13 @@ def test_vessel_starting_at_boundary(self): # The slight difference is due to randomness in vessel generation volume_boundary = np.sum(vessel_boundary.geometrical_volume) volume_inside = np.sum(vessel_inside.geometrical_volume) - + # Ensure both vessels have substantial volume self.assertGreater(volume_boundary, 100, "Vessel at boundary should have substantial volume") self.assertGreater(volume_inside, 100, "Vessel inside should have substantial volume") - + # Check that they are similar in size (within 20% tolerance) ratio = volume_boundary / volume_inside - self.assertGreater(ratio, 0.8, f"Vessel at boundary should be at least 80% of inside vessel size, got {ratio:.2%}") + self.assertGreater( + ratio, 0.8, f"Vessel at boundary should be at least 80% of inside vessel size, got {ratio:.2%}") self.assertLess(ratio, 1.2, f"Vessel at boundary should be at most 120% of inside vessel size, got {ratio:.2%}") From c6419d2c5d828467db57374364810f6571585b13 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Nov 2025 18:23:19 +0000 Subject: [PATCH 4/4] Security scan completed - no issues found Co-authored-by: jgroehl <7871475+jgroehl@users.noreply.github.com> --- simpa/utils/libraries/structure_library/VesselStructure.py | 1 + 1 file changed, 1 insertion(+) diff --git a/simpa/utils/libraries/structure_library/VesselStructure.py b/simpa/utils/libraries/structure_library/VesselStructure.py index df2247a7..528ae1c1 100644 --- a/simpa/utils/libraries/structure_library/VesselStructure.py +++ b/simpa/utils/libraries/structure_library/VesselStructure.py @@ -193,3 +193,4 @@ def define_vessel_structure_settings(vessel_start_mm: list, Tags.ADHERE_TO_DEFORMATION: adhere_to_deformation, Tags.STRUCTURE_TYPE: Tags.VESSEL_STRUCTURE } +# temp