From dfb183c9220382f5ae4e42fd7453eaf62846852d Mon Sep 17 00:00:00 2001 From: James Kerns Date: Tue, 8 Oct 2024 16:22:24 -0500 Subject: [PATCH 1/3] revert symmetric check --- pylinac/ct.py | 13 +------------ tests_basic/test_cheese.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/pylinac/ct.py b/pylinac/ct.py index a5cfffb2..fee5abd9 100644 --- a/pylinac/ct.py +++ b/pylinac/ct.py @@ -404,8 +404,7 @@ def phantom_roi(self) -> RegionProperties: )[0] is_too_large = self.catphan_size * 1.3 < catphan_region.filled_area is_too_small = catphan_region.filled_area < self.catphan_size / 1.3 - not_symmetric = not is_symmetric(catphan_region) - if is_too_small or is_too_large or not_symmetric: + if is_too_small or is_too_large: raise ValueError("Unable to find ROI of expected size of the phantom") return catphan_region @@ -2915,16 +2914,6 @@ def find_phantom_roll(self, func: Callable | None = None) -> float: return angle + 75 -def is_symmetric(region: RegionProperties, tolerance: float = 0.3) -> bool: - """Check symmetry of ROI by comparing x-axis size to y-axis size""" - ymin, xmin, ymax, xmax = region.bbox - y = abs(ymax - ymin) - x = abs(xmax - xmin) - if x > y * (1 + tolerance) or x < y * (1 - tolerance): - return False - return True - - def get_regions( slice_or_arr: Slice | np.array, fill_holes: bool = False, diff --git a/tests_basic/test_cheese.py b/tests_basic/test_cheese.py index a26ff7a4..a27dd5fa 100644 --- a/tests_basic/test_cheese.py +++ b/tests_basic/test_cheese.py @@ -395,3 +395,16 @@ class TestCIRS062MButsonEmptyButoOuter(CheeseMixin, TestCase): "16": 214, "17": 856, } + + +class TestCIRS062MShifted(CheeseMixin, TestCase): + model = CIRS062M + origin_slice = 30 + dir_path = ["Tomo", "CIRS062M"] + file_name = "CIRS bad, shifted.zip" + expected_roll = -0.55 + hu_values = { + "1": -3, + "8": 45, + "17": -489, + } From eb4517cc0ed12d249dfe289e1f54af4929854795 Mon Sep 17 00:00:00 2001 From: James Kerns Date: Tue, 8 Oct 2024 20:35:48 -0500 Subject: [PATCH 2/3] fix refinement error of a few datasets. --- pylinac/ct.py | 11 +++--- tests_basic/test_cbct.py | 80 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/pylinac/ct.py b/pylinac/ct.py index a5cfffb2..4af70d20 100644 --- a/pylinac/ct.py +++ b/pylinac/ct.py @@ -2823,6 +2823,9 @@ def refine_origin_slice(self, initial_slice_num: int) -> int: "angle": angle, "left width": troi["Left"].long_profile.field_width_px, "right width": troi["Right"].long_profile.field_width_px, + # the values AT the FWXM + "left center": troi["Left"].long_profile.y_at_x(left_wire), + "right center": troi["Right"].long_profile.y_at_x(right_wire), "left profile": troi["Left"].long_profile.values, "right profile": troi["Right"].long_profile.values, } @@ -2858,11 +2861,9 @@ def refine_origin_slice(self, initial_slice_num: int) -> int: continue # if the max pixel value of the angle set is closer to the overall median than the max # it means the wire isn't in the slice; drop it - max_pixel = max( - angle_set["left profile"].max(), angle_set["right profile"].max() - ) - delta_median = abs(median_pixel_val - max_pixel) - delta_max = abs(max_pixel_val - max_pixel) + fwxm_pixel = np.mean((angle_set["left center"], angle_set["right center"])) + delta_median = abs(median_pixel_val - fwxm_pixel) + delta_max = abs(max_pixel_val - fwxm_pixel) if delta_median < delta_max: angles.remove(angle_set) diff --git a/tests_basic/test_cbct.py b/tests_basic/test_cbct.py index ae7fe701..175994fa 100644 --- a/tests_basic/test_cbct.py +++ b/tests_basic/test_cbct.py @@ -1773,6 +1773,86 @@ class CatPhan604CoCr(CatPhan604Mixin, TestCase): lowcon_visible = 2 +@mark.directdensity +@mark.catphan604 +class CatPhan604SliceRefinementLocalization(CatPhan604Mixin, TestCase): + """A crazy scenario where the refinement algorithm failed due to the wire being at the edge of the + "long_profile". Also, this is a direct density scan. + """ + + file_name = "CatPhan604 - ramp edge.zip" + hu_origin_variance = 200 + origin_slice = 71 + hu_values = { + "Poly": -67, + "Acrylic": 94, + "Delrin": 114, + "Air": -997, + "Teflon": 364, + "PMP": -212, + "LDPE": -129, + "50% Bone": 335, + "20% Bone": 104, + } + thickness_slice_straddle = 0 + slice_thickness = 2.35 + unif_values = {"Center": -18, "Left": -17, "Right": -17, "Top": -17, "Bottom": -18} + mtf_values = {50: 0.30} + lowcon_visible = 6 + + +@mark.directdensity +@mark.catphan604 +class CatPhan604DD2(CatPhan604Mixin, TestCase): + """Direct density scan""" + + file_name = "CatPhan604 - DD2.zip" + hu_origin_variance = 200 + origin_slice = 74 + hu_values = { + "Poly": -36, + "Acrylic": 118, + "Delrin": 191, + "Air": -1017, + "Teflon": 540, + "PMP": -187, + "LDPE": -97, + "50% Bone": 380, + "20% Bone": 124, + } + thickness_slice_straddle = 0 + slice_thickness = 2.35 + unif_values = {"Center": 9, "Left": 9, "Right": 9, "Top": 9, "Bottom": 9} + mtf_values = {50: 0.30} + lowcon_visible = 6 + + +@mark.directdensity +@mark.catphan604 +class CatPhan604DD3(CatPhan604Mixin, TestCase): + """Direct density scan""" + + file_name = "CatPhan604 - DD3.zip" + hu_origin_variance = 200 + origin_slice = 71 + hu_values = { + "Poly": -65, + "Acrylic": 95, + "Delrin": 115, + "Air": -999, + "Teflon": 363, + "PMP": -212, + "LDPE": -125, + "50% Bone": 335, + "20% Bone": 105, + } + thickness_slice_straddle = 0 + slice_thickness = 2.35 + unif_values = {"Center": -20, "Left": -20, "Right": -20, "Top": -20, "Bottom": -20} + mtf_values = {50: 0.30} + lowcon_visible = 6 + + class CatPhan504NearEdge(CatPhan504Mixin, TestCase): file_name = "phantom_edge.zip" expected_roll = 1.4 From 18b27726b0a9251d842704233b4629e3c2fb5c4e Mon Sep 17 00:00:00 2001 From: James Kerns Date: Wed, 9 Oct 2024 08:36:13 -0500 Subject: [PATCH 3/3] remove locked call --- bitbucket-pipelines.yml | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index b7d68abc..401c82bc 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -40,7 +40,7 @@ definitions: name: Run CBCT Tests size: 2x script: - - uv run --locked pytest tests_basic/test_cbct.py -n 2 --cov=pylinac.cbct --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_cbct.py -n 2 --cov=pylinac.cbct --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -52,7 +52,7 @@ definitions: - step: &quart-tests name: Run Quart Tests script: - - uv run --locked pytest tests_basic/test_quart.py --cov=pylinac.quart --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_quart.py --cov=pylinac.quart --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -65,7 +65,7 @@ definitions: - step: &acr-tests name: Run ACR CT/MRI Tests script: - - uv run --locked pytest tests_basic/test_acr.py --cov=pylinac.acr --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_acr.py --cov=pylinac.acr --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -78,7 +78,7 @@ definitions: - step: &cheese-tests name: Run Cheese Phantom Tests script: - - uv run --locked pytest tests_basic/test_cheese.py --cov=pylinac.cheese --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_cheese.py --cov=pylinac.cheese --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -91,7 +91,7 @@ definitions: - step: &planar-tests name: Run Planar Imaging Tests script: - - uv run --locked pytest tests_basic/test_planar_imaging.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_planar_imaging.py --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -103,7 +103,7 @@ definitions: - step: &dlg-tests name: Run DLG Tests script: - - uv run --locked pytest tests_basic/test_dlg.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_dlg.py --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -115,7 +115,7 @@ definitions: - step: &field-analysis-tests name: Run Field Analysis Tests script: - - uv run --locked pytest tests_basic/test_field_analysis.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_field_analysis.py --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -127,7 +127,7 @@ definitions: - step: &machine-log-tests name: Run Machine Logs Tests script: - - uv run --locked pytest tests_basic/test_logs.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_logs.py --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -139,7 +139,7 @@ definitions: - step: &picket-fence-tests name: Run Picket Fence Tests script: - - uv run --locked pytest tests_basic/test_picketfence.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_picketfence.py --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -151,7 +151,7 @@ definitions: - step: &starshot-tests name: Run Starshot Tests script: - - uv run --locked pytest tests_basic/test_starshot.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_starshot.py --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -163,7 +163,7 @@ definitions: - step: &calibration-tests name: Run TG-51/TRS-398 Tests script: - - uv run --locked pytest tests_basic/test_tg51.py tests_basic/test_trs398.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_tg51.py tests_basic/test_trs398.py --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -176,7 +176,7 @@ definitions: - step: &vmat-tests name: Run VMAT Tests script: - - uv run --locked pytest tests_basic/test_vmat.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_vmat.py --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -189,7 +189,7 @@ definitions: name: Run Winston-Lutz Tests size: 2x script: - - uv run --locked pytest tests_basic/test_winstonlutz.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_winstonlutz.py --cov-report term --junitxml=./test-reports/pytest_results.xml condition: changesets: includePaths: @@ -200,7 +200,7 @@ definitions: name: Run Winston-Lutz Multi-Target Multi-Field Tests size: 2x script: - - uv run --locked pytest tests_basic/test_winstonlutz_mtmf.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_winstonlutz_mtmf.py --cov-report term --junitxml=./test-reports/pytest_results.xml condition: changesets: includePaths: @@ -210,7 +210,7 @@ definitions: - step: &plan-generator-tests name: Plan generator tests script: - - uv run --locked pytest tests_basic/test_plan_generator.py tests_basic/test_generated_plans.py --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/test_plan_generator.py tests_basic/test_generated_plans.py --cov-report term --junitxml=./test-reports/pytest_results.xml condition: changesets: includePaths: @@ -221,7 +221,7 @@ definitions: - step: &core-module-tests name: Run core module tests script: - - uv run --locked pytest tests_basic/core --cov-report term --junitxml=./test-reports/pytest_results.xml + - uv run pytest tests_basic/core --cov-report term --junitxml=./test-reports/pytest_results.xml caches: - testfiles condition: @@ -239,7 +239,7 @@ definitions: - tar -xf gcloud_cli.tar.gz - ./google-cloud-sdk/install.sh --quiet - export PATH="./google-cloud-sdk/bin:$PATH" - - uv run --locked nox -s update_dev_kraken + - uv run nox -s update_dev_kraken - step: &run-min-python-version name: Run against min Python version image: ghcr.io/astral-sh/uv:python3.9-bookworm-slim