From e130ae2121ce8c16ff71cd05420a8ff3470287b4 Mon Sep 17 00:00:00 2001 From: Matthias Walle <92020703+wallematthias@users.noreply.github.com> Date: Tue, 27 Oct 2026 16:32:26 -0600 Subject: [PATCH] Expose hip shaft length in ogoFEA help --- ogo/cli/GenerateFEM.py | 18 ++++++++++++++++++ tests/cli/test_GenerateFEM.py | 21 +++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/ogo/cli/GenerateFEM.py b/ogo/cli/GenerateFEM.py index b7286ab..800a5e0 100644 --- a/ogo/cli/GenerateFEM.py +++ b/ogo/cli/GenerateFEM.py @@ -23,6 +23,7 @@ solve_report_profile as spine_solve_report_profile, ) from ogo.fea.femur import ( + DEFAULT_FEMUR_GREATER_TROCHANTER_DISTAL_LENGTH_MM, solve_report_profile as femur_solve_report_profile, ) @@ -642,6 +643,18 @@ def build_parser() -> argparse.ArgumentParser: default=None, help="Femur side to process. Repeatable; defaults to both.", ) + hip.add_argument( + "--femur_greater_trochanter_distal_length", + type=float, + default=None, + metavar="MM", + help=( + "Retained complete flat shaft length from the distal edge of the " + "GT support (greater-trochanter disk), after removing the incomplete " + "distal section. Insufficient coverage fails generation. " + f"Default: {DEFAULT_FEMUR_GREATER_TROCHANTER_DISTAL_LENGTH_MM:g} mm." + ), + ) return parser @@ -723,6 +736,11 @@ def main(argv: Optional[Sequence[str]] = None) -> None: if args.model_type == "hip": femur_extra_args = pistoia_mask_args + list(extra_args) + if args.femur_greater_trochanter_distal_length is not None: + femur_extra_args.extend([ + "--femur_greater_trochanter_distal_length", + str(args.femur_greater_trochanter_distal_length), + ]) for side in expand_sides(args.side or ["both"]): cmd = build_femur_command( calibrated_image=args.calibrated_image, diff --git a/tests/cli/test_GenerateFEM.py b/tests/cli/test_GenerateFEM.py index 6788423..e6d6d03 100644 --- a/tests/cli/test_GenerateFEM.py +++ b/tests/cli/test_GenerateFEM.py @@ -12,6 +12,27 @@ _SPEC.loader.exec_module(GenerateFEM) +def test_hip_help_explains_retained_shaft_length(capsys): + with pytest.raises(SystemExit) as exc: + GenerateFEM.main(["hip", "--help"]) + assert exc.value.code == 0 + help_text = " ".join(capsys.readouterr().out.split()) + assert "--femur_greater_trochanter_distal_length" in help_text + assert "GT support" in help_text + assert "10 mm" in help_text + + +def test_hip_shaft_length_is_forwarded_once(capsys): + GenerateFEM.main([ + "hip", "density.nii.gz", "hip_mask.nii.gz", "--side", "left", + "--femur_greater_trochanter_distal_length", "15", + "--dry-run", "--no-solve", + ]) + command = capsys.readouterr().out + assert command.count("--femur_greater_trochanter_distal_length") == 1 + assert "--femur_greater_trochanter_distal_length 15.0" in command + + def test_generation_thread_limit_applies_to_vtk_and_itk(): vtk = pytest.importorskip("vtk") sitk = pytest.importorskip("SimpleITK")