From 841c363fb28c00757bb4b9e6dddafbaa3c3cfb52 Mon Sep 17 00:00:00 2001 From: Andy Wickert Date: Wed, 10 Jun 2026 09:50:10 -0500 Subject: [PATCH 1/3] v.flexure: fix IndexError in get_points_xy for empty vector map np.array([], dtype=float) has shape (0,), so coords[:, 0] raises IndexError. Return empty 1-D arrays directly when the map has no rows. Co-Authored-By: Claude Sonnet 4.6 --- src/vector/v.flexure/v.flexure.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vector/v.flexure/v.flexure.py b/src/vector/v.flexure/v.flexure.py index 648737eb38..e65161ad1d 100644 --- a/src/vector/v.flexure/v.flexure.py +++ b/src/vector/v.flexure/v.flexure.py @@ -156,6 +156,8 @@ def get_points_xy(vect_name): "v.out.ascii", input=vect_name, format="point", separator="space", quiet=True ) rows = [line.split() for line in out.strip().splitlines() if line.strip()] + if not rows: + return np.array([]), np.array([]) coords = np.array([[float(r[0]), float(r[1])] for r in rows], dtype=float) return coords[:, 0], coords[:, 1] # x, y From 61cc5f32d15803025664b34da3c47cea7894b70a Mon Sep 17 00:00:00 2001 From: Andy Wickert Date: Wed, 10 Jun 2026 09:50:24 -0500 Subject: [PATCH 2/3] v.flexure: add gs.fatal guard for empty input vector map A zero-point input produces all-zero deflection in gFlex (mathematically correct) but is almost certainly a user error. Fail early with a clear GRASS-idiomatic message rather than silently producing a flat output. Co-Authored-By: Claude Sonnet 4.6 --- src/vector/v.flexure/v.flexure.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/vector/v.flexure/v.flexure.py b/src/vector/v.flexure/v.flexure.py index e65161ad1d..8969f39225 100644 --- a/src/vector/v.flexure/v.flexure.py +++ b/src/vector/v.flexure/v.flexure.py @@ -221,6 +221,8 @@ def main(): # x, y, q — load point coordinates and magnitudes flex.x, flex.y = get_points_xy(options["input"]) + if len(flex.x) == 0: + gs.fatal(_("Input vector map <%s> contains no points.") % options["input"]) vect_db = gs.vector_db_select(options["input"]) col_names = np.array(vect_db["columns"]) q_col = col_names == options["column"] From 00986863369af0f521aa43e2c946ec94d61e6023 Mon Sep 17 00:00:00 2001 From: Andy Wickert Date: Wed, 10 Jun 2026 15:57:18 -0500 Subject: [PATCH 3/3] v.flexure tests: add test_empty_input to TestVFlexureInputErrors Covers the gs.fatal guard added for a zero-point input vector map. Uses v.edit tool=create to produce an empty map fixture. Co-Authored-By: Claude Sonnet 4.6 --- src/vector/v.flexure/testsuite/test_v_flexure.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/vector/v.flexure/testsuite/test_v_flexure.py b/src/vector/v.flexure/testsuite/test_v_flexure.py index 60e83606fa..ff879132db 100644 --- a/src/vector/v.flexure/testsuite/test_v_flexure.py +++ b/src/vector/v.flexure/testsuite/test_v_flexure.py @@ -579,6 +579,7 @@ class TestVFlexureInputErrors(TestCase): """Input-validation errors raised inside main() — gFlex must be importable.""" loads = "test_vflex_ierr_loads" + empty_loads = "test_vflex_ierr_empty" @classmethod def setUpClass(cls): @@ -605,11 +606,15 @@ def setUpClass(cls): value="1e15", where="cat=1", ) + cls.runModule("v.edit", map=cls.empty_loads, tool="create") @classmethod def tearDownClass(cls): cls.del_temp_region() cls.runModule("g.remove", flags="f", type="vector", name=cls.loads, quiet=True) + cls.runModule( + "g.remove", flags="f", type="vector", name=cls.empty_loads, quiet=True + ) def test_missing_column(self): """Module exits with error when the named column is absent from the input map.""" @@ -622,6 +627,17 @@ def test_missing_column(self): output="dummy_out", ) + def test_empty_input(self): + """Module exits with error when the input vector map contains no points.""" + self.assertModuleFail( + "v.flexure", + input=self.empty_loads, + column="q", + te="10000", + te_units="m", + output="dummy_out", + ) + if __name__ == "__main__": test()