From 849e5796170c47eb5365a1dbce3cd6fbebcbc680 Mon Sep 17 00:00:00 2001 From: James Kerns Date: Thu, 5 Sep 2024 14:25:18 -0500 Subject: [PATCH 1/2] allow cropping of 0 pixels. --- docs/source/changelog.rst | 5 +++++ pylinac/core/image.py | 6 +++++- pyproject.toml | 1 + tests_basic/core/test_image.py | 13 ++++++++++--- tests_basic/test_picketfence.py | 6 +++++- 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index bae2d884..e36e8704 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -36,6 +36,11 @@ ACR MRI the full circle of the phantom. The algorithm no longer relies on this assumption and is robust to these air gaps for the geometric distortion analysis. +Core +^^^^ + +* Performing :meth:`~pylinac.core.image.BaseImage.crop` on an image now allows for a ``pixels`` input of 0. This allows for a no-op crop. + v 3.26.0 -------- diff --git a/pylinac/core/image.py b/pylinac/core/image.py index 033c642c..fcf5e578 100644 --- a/pylinac/core/image.py +++ b/pylinac/core/image.py @@ -640,8 +640,12 @@ def crop( edges : tuple Which edges to remove from. Can be any combination of the four edges. """ - if pixels <= 0: + if pixels < 0: raise ValueError("Pixels to remove must be a positive number") + if pixels == 0: + # using 0 will cause an error in numpy slicing + # we also want to be able to handle a no-op + return if "top" in edges: self.array = self.array[pixels:, :] if "bottom" in edges: diff --git a/pyproject.toml b/pyproject.toml index 85a4d32e..61d03d30 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,7 @@ dev = [ "sphinx-copybutton", "pre-commit", "hatch", + "parameterized", ] docs = [ "sphinx", diff --git a/tests_basic/core/test_image.py b/tests_basic/core/test_image.py index 83276bc7..e4a06253 100644 --- a/tests_basic/core/test_image.py +++ b/tests_basic/core/test_image.py @@ -14,6 +14,7 @@ import PIL.Image import pydicom from numpy.testing import assert_array_almost_equal +from parameterized import parameterized from pydicom.uid import UID from pylinac import settings @@ -332,6 +333,12 @@ def test_is_image(self): ) +class TT(TestCase): + @parameterized.expand([(1,), (2,), (3,)]) + def test_this(self, thing): + self.assertEqual(thing, 1) + + class TestBaseImage(TestCase): """Test the basic methods of BaseImage. Since it's a semi-abstract class, its subclasses (DicomImage, ArrayImage, and FileImage) are tested.""" @@ -342,9 +349,9 @@ def setUp(self): array = np.arange(42).reshape(6, 7) self.arr = image.load(array) - def test_crop(self): + @parameterized.expand([15, 0]) + def test_crop(self, crop): """Remove the edges from a pixel array.""" - crop = 15 orig_shape = self.img.shape orig_dpi = self.img.dpi self.img.crop(crop) @@ -356,7 +363,7 @@ def test_crop(self): def test_crop_must_be_positive(self): """Crop must be manifestly positive""" - crop = 0 + crop = -1 with self.assertRaises(ValueError): self.img.crop(crop) diff --git a/tests_basic/test_picketfence.py b/tests_basic/test_picketfence.py index e8f97207..8dea115e 100644 --- a/tests_basic/test_picketfence.py +++ b/tests_basic/test_picketfence.py @@ -479,6 +479,7 @@ class PFTestMixin(CloudFileMixin): abs_median_error = 0 sag_adjustment = 0 invert = False + crop_mm: int = 3 passes = True log = None mean_picket_spacing = 15 @@ -496,7 +497,9 @@ def get_logfile(cls): @classmethod def setUpClass(cls): - cls.pf = PicketFence(cls.get_filename(), log=cls.get_logfile()) + cls.pf = PicketFence( + cls.get_filename(), log=cls.get_logfile(), crop_mm=cls.crop_mm + ) if cls.pass_num_pickets: cls.pf.analyze( sag_adjustment=cls.sag_adjustment, @@ -581,6 +584,7 @@ class PerfectSimulation(PFTestMixin, TestCase): abs_median_error = 0 num_pickets = 5 mean_picket_spacing = 20 + crop_mm = 0 class Rotated2Simulation(PFTestMixin, TestCase): From 3ab04a66824a44802191482f1bdcb23462bc9738 Mon Sep 17 00:00:00 2001 From: James Kerns Date: Thu, 5 Sep 2024 14:28:38 -0500 Subject: [PATCH 2/2] drop dummy test case --- tests_basic/core/test_image.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests_basic/core/test_image.py b/tests_basic/core/test_image.py index e4a06253..79637f6d 100644 --- a/tests_basic/core/test_image.py +++ b/tests_basic/core/test_image.py @@ -333,12 +333,6 @@ def test_is_image(self): ) -class TT(TestCase): - @parameterized.expand([(1,), (2,), (3,)]) - def test_this(self, thing): - self.assertEqual(thing, 1) - - class TestBaseImage(TestCase): """Test the basic methods of BaseImage. Since it's a semi-abstract class, its subclasses (DicomImage, ArrayImage, and FileImage) are tested."""