From be6bc9cfa23a9519405cee891dd517c68911ab22 Mon Sep 17 00:00:00 2001 From: Neil Vaytet Date: Wed, 2 Oct 2024 22:25:35 +0200 Subject: [PATCH 1/4] allow to create choppers from centers and widths of cutouts in addition to open and close angles --- src/tof/chopper.py | 37 +++++++++++++++++++++++++++++++------ tests/chopper_test.py | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 6 deletions(-) diff --git a/src/tof/chopper.py b/src/tof/chopper.py index 19306eb..2c22c35 100644 --- a/src/tof/chopper.py +++ b/src/tof/chopper.py @@ -29,10 +29,6 @@ class Chopper: ---------- frequency: The frequency of the chopper. Must be positive. - open: - The opening angles of the chopper cutouts. - close: - The closing angles of the chopper cutouts. distance: The distance from the source to the chopper. phase: @@ -41,17 +37,32 @@ class Chopper: to the chopper rotation direction. For example, if the chopper rotates clockwise, a phase of 10 degrees will shift all window angles by 10 degrees in the anticlockwise direction, which will result in the windows opening later. + open: + The opening angles of the chopper cutouts. + close: + The closing angles of the chopper cutouts. + center: + The center of the chopper cutouts. + width: + The width of the chopper cutouts. name: The name of the chopper. + + Notes + ----- + Either `open` and `close` or `center` and `width` must be provided, but not both. """ def __init__( self, + *, frequency: sc.Variable, - open: sc.Variable, - close: sc.Variable, distance: sc.Variable, phase: sc.Variable, + open: sc.Variable | None = None, + close: sc.Variable | None = None, + center: sc.Variable | None = None, + width: sc.Variable | None = None, direction: Direction = Clockwise, name: str = "", ): @@ -64,6 +75,20 @@ def __init__( f", got {direction}." ) self.direction = direction + # Check that either open/close or center/width are provided, but not both + if tuple(x for x in (open, close, center, width) if x is not None) not in ( + (open, close), + (center, width), + ): + raise ValueError( + "Either open/close or center/width must be provided, got" + f" open={open}, close={close}, center={center}, width={width}." + ) + if open is None: + half_width = width * 0.5 + open = center - half_width + close = center + half_width + self.open = (open if open.dims else open.flatten(to='cutout')).to( dtype=float, copy=False ) diff --git a/tests/chopper_test.py b/tests/chopper_test.py index add8a31..c81a970 100644 --- a/tests/chopper_test.py +++ b/tests/chopper_test.py @@ -291,3 +291,43 @@ def test_bad_direction_raises(): distance=d, direction=1, ) + + +def test_chopper_create_from_centers_and_widths(): + f = 10.0 * Hz + center = sc.array(dims=['cutout'], values=[15.0, 46.0], unit='deg') + width = sc.array(dims=['cutout'], values=[10.0, 16.0], unit='deg') + chopper = tof.Chopper( + frequency=f, + center=center, + width=width, + phase=0.0 * deg, + distance=5.0 * meter, + ) + assert sc.allclose(chopper.open, center - width / 2) + assert sc.allclose(chopper.close, center + width / 2) + + expected = tof.Chopper( + frequency=f, + open=sc.array(dims=['cutout'], values=[10.0, 38.0], unit='deg'), + close=sc.array(dims=['cutout'], values=[20.0, 54.0], unit='deg'), + phase=0.0 * deg, + distance=5.0 * meter, + ) + assert sc.allclose(chopper.open, expected.open) + assert sc.allclose(chopper.close, expected.close) + + +def test_chopper_create_raises_when_both_edges_and_centers_are_supplied(): + with pytest.raises( + ValueError, match="Either open/close or center/width must be provided" + ): + tof.Chopper( + frequency=10.0 * Hz, + open=10.0 * deg, + close=20.0 * deg, + center=15.0 * deg, + width=10.0 * deg, + phase=0.0 * deg, + distance=5.0 * meter, + ) From b879dd95b2d6a1c9089a910f3d0f33875cebe751 Mon Sep 17 00:00:00 2001 From: Neil Vaytet Date: Thu, 3 Oct 2024 11:48:54 +0200 Subject: [PATCH 2/4] use plural --- src/tof/chopper.py | 28 ++++++++++++++-------------- tests/chopper_test.py | 18 +++++++++--------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/tof/chopper.py b/src/tof/chopper.py index 2c22c35..6bba09b 100644 --- a/src/tof/chopper.py +++ b/src/tof/chopper.py @@ -41,16 +41,16 @@ class Chopper: The opening angles of the chopper cutouts. close: The closing angles of the chopper cutouts. - center: - The center of the chopper cutouts. - width: - The width of the chopper cutouts. + centers: + The centers of the chopper cutouts. + widths: + The widths of the chopper cutouts. name: The name of the chopper. Notes ----- - Either `open` and `close` or `center` and `width` must be provided, but not both. + Either `open` and `close` or `centers` and `widths` must be provided, but not both. """ def __init__( @@ -61,8 +61,8 @@ def __init__( phase: sc.Variable, open: sc.Variable | None = None, close: sc.Variable | None = None, - center: sc.Variable | None = None, - width: sc.Variable | None = None, + centers: sc.Variable | None = None, + widths: sc.Variable | None = None, direction: Direction = Clockwise, name: str = "", ): @@ -76,18 +76,18 @@ def __init__( ) self.direction = direction # Check that either open/close or center/width are provided, but not both - if tuple(x for x in (open, close, center, width) if x is not None) not in ( + if tuple(x for x in (open, close, centers, widths) if x is not None) not in ( (open, close), - (center, width), + (centers, widths), ): raise ValueError( - "Either open/close or center/width must be provided, got" - f" open={open}, close={close}, center={center}, width={width}." + "Either open/close or centers/widths must be provided, got" + f" open={open}, close={close}, center={centers}, width={widths}." ) if open is None: - half_width = width * 0.5 - open = center - half_width - close = center + half_width + half_width = widths * 0.5 + open = centers - half_width + close = centers + half_width self.open = (open if open.dims else open.flatten(to='cutout')).to( dtype=float, copy=False diff --git a/tests/chopper_test.py b/tests/chopper_test.py index c81a970..2da9ad0 100644 --- a/tests/chopper_test.py +++ b/tests/chopper_test.py @@ -295,17 +295,17 @@ def test_bad_direction_raises(): def test_chopper_create_from_centers_and_widths(): f = 10.0 * Hz - center = sc.array(dims=['cutout'], values=[15.0, 46.0], unit='deg') - width = sc.array(dims=['cutout'], values=[10.0, 16.0], unit='deg') + centers = sc.array(dims=['cutout'], values=[15.0, 46.0], unit='deg') + widths = sc.array(dims=['cutout'], values=[10.0, 16.0], unit='deg') chopper = tof.Chopper( frequency=f, - center=center, - width=width, + centers=centers, + widths=widths, phase=0.0 * deg, distance=5.0 * meter, ) - assert sc.allclose(chopper.open, center - width / 2) - assert sc.allclose(chopper.close, center + width / 2) + assert sc.allclose(chopper.open, centers - widths / 2) + assert sc.allclose(chopper.close, centers + widths / 2) expected = tof.Chopper( frequency=f, @@ -320,14 +320,14 @@ def test_chopper_create_from_centers_and_widths(): def test_chopper_create_raises_when_both_edges_and_centers_are_supplied(): with pytest.raises( - ValueError, match="Either open/close or center/width must be provided" + ValueError, match="Either open/close or centers/widths must be provided" ): tof.Chopper( frequency=10.0 * Hz, open=10.0 * deg, close=20.0 * deg, - center=15.0 * deg, - width=10.0 * deg, + centers=15.0 * deg, + widths=10.0 * deg, phase=0.0 * deg, distance=5.0 * meter, ) From f839777a0f13f91f5992b92cc9e0a3a1f2b2a160 Mon Sep 17 00:00:00 2001 From: Neil Vaytet Date: Thu, 3 Oct 2024 11:49:48 +0200 Subject: [PATCH 3/4] update comment --- src/tof/chopper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tof/chopper.py b/src/tof/chopper.py index 6bba09b..9bd647a 100644 --- a/src/tof/chopper.py +++ b/src/tof/chopper.py @@ -75,7 +75,7 @@ def __init__( f", got {direction}." ) self.direction = direction - # Check that either open/close or center/width are provided, but not both + # Check that either open/close or centers/widths are provided, but not both if tuple(x for x in (open, close, centers, widths) if x is not None) not in ( (open, close), (centers, widths), From 8d61a4879fd571eaa8d4797cf90691a9e6eab7f8 Mon Sep 17 00:00:00 2001 From: Neil Vaytet Date: Thu, 3 Oct 2024 11:50:20 +0200 Subject: [PATCH 4/4] update names in error message --- src/tof/chopper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tof/chopper.py b/src/tof/chopper.py index 9bd647a..1f71bdb 100644 --- a/src/tof/chopper.py +++ b/src/tof/chopper.py @@ -82,7 +82,7 @@ def __init__( ): raise ValueError( "Either open/close or centers/widths must be provided, got" - f" open={open}, close={close}, center={centers}, width={widths}." + f" open={open}, close={close}, centers={centers}, widths={widths}." ) if open is None: half_width = widths * 0.5