diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e0eb24a..f7499159 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,16 +55,16 @@ jobs: - name: Test package run: python -m pytest -ra - # root: - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v2 + root: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 - # - name: Get Conda - # uses: conda-incubator/setup-miniconda@v2 - # with: - # environment-file: environment.yml - # activate-environment: vector + - name: Get Conda + uses: conda-incubator/setup-miniconda@v2 + with: + environment-file: environment.yml + activate-environment: vector # - name: Run tests # shell: "bash -l {0}" diff --git a/setup.py b/setup.py index eb40b550..2eb02665 100644 --- a/setup.py +++ b/setup.py @@ -10,6 +10,7 @@ "awkward": ["awkward>=1.2.0"], "test": [ "pytest>=4.6", + "hypothesis>=6", ], "test_extras": [ "uncompyle6", diff --git a/src/vector/_compute/lorentz/dot.py b/src/vector/_compute/lorentz/dot.py index 24b554b4..d5001ef4 100644 --- a/src/vector/_compute/lorentz/dot.py +++ b/src/vector/_compute/lorentz/dot.py @@ -109,10 +109,11 @@ def make_conversion( to_t2 = t.rhophi_eta_tau def f(lib, coord11, coord12, coord13, coord14, coord21, coord22, coord23, coord24): - return lib.absolute( - to_t1(lib, coord11, coord12, coord13, coord14) - * to_t2(lib, coord21, coord22, coord23, coord24) - ) - spatial_dot(lib, coord11, coord12, coord13, coord21, coord22, coord23) + t1 = to_t1(lib, coord11, coord12, coord13, coord14) + t2 = to_t1(lib, coord21, coord22, coord23, coord24) + return (t1 * t2) - spatial_dot( + lib, coord11, coord12, coord13, coord21, coord22, coord23 + ) dispatch_map[ azimuthal1, longitudinal1, temporal1, azimuthal2, longitudinal2, temporal2 diff --git a/src/vector/_compute/spatial/mag2.py b/src/vector/_compute/spatial/mag2.py index 32f514e0..a70008cc 100644 --- a/src/vector/_compute/spatial/mag2.py +++ b/src/vector/_compute/spatial/mag2.py @@ -32,6 +32,7 @@ def xy_z(lib, x, y, z): def xy_theta(lib, x, y, theta): + # FIXME?: returns 'nan' when theta == 0.0 return (x ** 2 + y ** 2) / lib.sin(theta) ** 2 diff --git a/tests/root/test_EulerAngles.py b/tests/root/test_EulerAngles.py new file mode 100644 index 00000000..4dd0e666 --- /dev/null +++ b/tests/root/test_EulerAngles.py @@ -0,0 +1,85 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# 4D constructor arguments to get all the weird cases. +constructor = [ + (0, 0, 0, 0), + (0, 0, 1, 0), # theta == 0.0 + (0, 0, -1, 0), + (0, 0, 1, 0), + (0, 0, 0, 4294967296), + (0, 4294967296, 0, 0), + (0, 0, 0, 10), + (0, 0, 0, -10), + (1, 2, 3, 0), + (1, 2, 3, 10), + (1, 2, 3, -10), + (1.0, 2.0, 3.0, 2.5), + (1, 2, 3, 2.5), + (1, 2, 3, -2.5), +] + +# Coordinate conversion methods to apply to the VectorObject4D. +coordinate_list = [ + "to_xyzt", + "to_xythetat", # may fail for constructor2 + "to_xyetat", + "to_rhophizt", + "to_rhophithetat", + "to_rhophietat", + "to_xyztau", + "to_xythetatau", + "to_xyetatau", + "to_rhophiztau", + "to_rhophithetatau", + "to_rhophietatau", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param diff --git a/tests/root/test_Polar2DVector.py b/tests/root/test_Polar2DVector.py new file mode 100644 index 00000000..27c7b8d3 --- /dev/null +++ b/tests/root/test_Polar2DVector.py @@ -0,0 +1,531 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import numpy as np +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.Polar2DVector constructor arguments to get all the weird cases. +# r > 0 and phi from 0 to 360 deg? +constructor = [ + (0, 0), + (0, 10), + (1, 0), + (10, 0), + (1, 10), + (10.0, 10), + (1.0, 2.5), + (1, 2.5), + (1, 6.283185307179586), +] + +# Coordinate conversion methods to apply to the VectorObject2D. +coordinate_list = [ + "to_xy", + "to_rhophi", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.25 * np.pi, + -0.25 * np.pi, + 0.5 * np.pi, + -0.5 * np.pi, + np.pi, + -np.pi, + 2 * np.pi, + -2 * np.pi, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param + + +# Run a test that compares ROOT's 'Dot()' with vector's 'dot' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Dot(constructor, coordinates): + assert ROOT.Math.Polar2DVector(*constructor).Dot( + ROOT.Math.Polar2DVector(*constructor) + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().dot( + getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + ) + ) + + +# Run the same tests within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fuzz_Dot(constructor1, constructor2, coordinates): + assert ROOT.Math.Polar2DVector(*constructor1).Dot( + ROOT.Math.Polar2DVector(*constructor2) + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor1))), coordinates + )().dot( + getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor2))), coordinates + )() + ), + rel=1e-6, + abs=1e-6, + ) + + +# Run a test that compares ROOT's 'Mag2()' with vector's 'rho2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mag2(constructor, coordinates): + assert ROOT.Math.Polar2DVector(*constructor).Mag2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().rho2 + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_Mag2(constructor, coordinates): + assert ROOT.Math.Polar2DVector(*constructor).Mag2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().rho2 + ) + + +# Run a test that compares ROOT's 'R()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mag(constructor, coordinates): + assert ROOT.Math.sqrt( + ROOT.Math.Polar2DVector(*constructor).Mag2() + ) == pytest.approx( + getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)().rho + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_Mag(constructor, coordinates): + assert ROOT.Math.sqrt( + ROOT.Math.Polar2DVector(*constructor).Mag2() + ) == pytest.approx( + getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)().rho + ) + + +# Run a test that compares ROOT's 'Phi()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Phi(constructor, coordinates): + assert ROOT.Math.Polar2DVector(*constructor).Phi() == pytest.approx( + getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)().phi + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_Phi(constructor, coordinates): + assert ROOT.Math.Polar2DVector(*constructor).Phi() == pytest.approx( + getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)().phi + ) + + +# Run a test that compares ROOT's 'Rotate()' with vector's 'rotateZ' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Rotate(constructor, angle, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor) + ref_vec.Rotate(angle) + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().rotateZ(angle) + res_vec = vec.rotateZ(angle) + assert ref_vec.R() == pytest.approx(res_vec.rho) and ref_vec.Phi() == pytest.approx( + res_vec.phi + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + angle=st.floats(min_value=-10e7, max_value=10e7) + | st.integers(min_value=-10e7, max_value=10e7), +) +def test_fuzz_Rotate(constructor, angle, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor) + ref_vec.Rotate(angle) + vec = getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + res_vec = vec.rotateZ(angle) + assert ref_vec.R() == pytest.approx(res_vec.rho) and ref_vec.Phi() == pytest.approx( + res_vec.phi + ) + + +# Run a test that compares ROOT's 'Unit()' with vector's 'unit' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Unit(constructor, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).Unit() + vec = getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + res_vec = vec.unit + assert ref_vec.R() == pytest.approx( + res_vec().rho + ) and ref_vec.Phi() == pytest.approx(res_vec().phi) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_Unit(constructor, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).Unit() + vec = getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + res_vec = vec.unit + assert ref_vec.R() == pytest.approx( + res_vec().rho + ) and ref_vec.Phi() == pytest.approx(res_vec().phi) + + +# Run a test that compares ROOT's 'X()' and 'Y()' with vector's 'x' and 'y' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_X_and_Y(constructor, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor) + vec = getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + assert ref_vec.X() == pytest.approx(vec.x) and ref_vec.Y() == pytest.approx(vec.y) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_X_and_Y(constructor, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor) + vec = getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + assert ref_vec.X() == pytest.approx(vec.x) and ref_vec.Y() == pytest.approx(vec.y) + + +# Run a test that compares ROOT's '__add__' with vector's 'add' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_add(constructor, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).__add__( + ROOT.Math.Polar2DVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().add( + getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + ) + assert ref_vec.R() == pytest.approx(vec.rho) and ref_vec.Phi() == pytest.approx( + vec.phi + ) + + +# Run the same tests within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fuzz_add(constructor1, constructor2, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor1).__add__( + ROOT.Math.Polar2DVector(*constructor2) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor1))), coordinates + )().add( + getattr(vector.obj(**dict(zip(["rho", "phi"], constructor2))), coordinates)() + ) + assert ref_vec.R() == pytest.approx(vec.rho) and ref_vec.Phi() == pytest.approx( + vec.phi + ) + + +# Run a test that compares ROOT's '__sub__' with vector's 'subtract' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_sub(constructor, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).__sub__( + ROOT.Math.Polar2DVector(*constructor) + ) + vec1 = getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + vec2 = getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + res_vec = vec1.subtract(vec2) + assert ref_vec.R() == pytest.approx(res_vec.rho) and ref_vec.Phi() == pytest.approx( + res_vec.phi + ) + + +# Run the same tests within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fuzz_sub(constructor1, constructor2, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor1).__sub__( + ROOT.Math.Polar2DVector(*constructor2) + ) + vec1 = getattr(vector.obj(**dict(zip(["rho", "phi"], constructor1))), coordinates)() + vec2 = getattr(vector.obj(**dict(zip(["rho", "phi"], constructor2))), coordinates)() + res_vec = vec1.subtract(vec2) + assert ref_vec.R() == pytest.approx(res_vec.rho) and ref_vec.Phi() == pytest.approx( + res_vec.phi + ) + + +# Run a test that compares ROOT's '__neg__' with vector's '__neg__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_neg(constructor, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().__neg__ + assert ref_vec.R() == pytest.approx(vec().rho) and ref_vec.Phi() == pytest.approx( + vec().phi + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_neg(constructor, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().__neg__ + assert ref_vec.R() == pytest.approx(vec().rho) and ref_vec.Phi() == pytest.approx( + vec().phi + ) + + +# Run a test that compares ROOT's '__mul__' with vector's 'mul' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.R() == pytest.approx(vec.rho) and ref_vec.Phi() == pytest.approx( + vec.phi + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + scalar=st.floats(min_value=-10e7, max_value=10e7) + | st.integers(min_value=-10e7, max_value=10e7), +) +def test_fuzz_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.R() == pytest.approx(vec.rho) and ref_vec.Phi() == pytest.approx( + vec.phi + ) + + +# Run a test that compares ROOT's '__truediv__' with vector's '__truediv__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.R() == pytest.approx(vec.rho) and ref_vec.Phi() == pytest.approx( + vec.phi + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + scalar=st.floats(min_value=-10e7, max_value=10e7) + | st.integers(min_value=-10e7, max_value=10e7), +) +def test_fuzz_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.R() == pytest.approx(vec.rho) and ref_vec.Phi() == pytest.approx( + vec.phi + ) + + +# Run a test that compares ROOT's '__eq__' with vector's 'isclose' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_eq(constructor, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).__eq__( + ROOT.Math.Polar2DVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().isclose( + getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + ) + assert ref_vec == vec + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_eq(constructor, coordinates): + ref_vec = ROOT.Math.Polar2DVector(*constructor).__eq__( + ROOT.Math.Polar2DVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates + )().equal( + getattr(vector.obj(**dict(zip(["rho", "phi"], constructor))), coordinates)() + ) + assert ref_vec == vec diff --git a/tests/root/test_Polar3DVector.py b/tests/root/test_Polar3DVector.py new file mode 100644 index 00000000..4bcb9db8 --- /dev/null +++ b/tests/root/test_Polar3DVector.py @@ -0,0 +1,311 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import numpy as np +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.Polar3DVector constructor arguments to get all the weird cases. +constructor = [ + (0, 0, 0), + (0, 10, 0), + (0, -10, 0), + (1, 0, 0), + (1, 10, 0), + (1, -10, 0), + (1.0, 2.5, 2.0), + (1, 2.5, 2.0), + (1, -2.5, 2.0), +] + +# Coordinate conversion methods to apply to the VectorObject2D. +coordinate_list = [ + "to_xyz", + "to_rhophieta", + "to_rhophitheta", + "to_rhophiz", + "to_xyeta", + "to_xytheta", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param + + +# Run a test that compares ROOT's 'Dot()' with vector's 'dot' for all cases. +# rho = r*sin(theta) +@pytest.mark.parametrize("constructor", constructor) +def test_Dot(constructor, coordinates): + assert ROOT.Math.Polar3DVector(*constructor).Dot( + ROOT.Math.Polar3DVector(*constructor) + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )().dot( + getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), + coordinates, + )() + ) + ) + + +# Run the same tests within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fuzz_Dot(constructor1, constructor2, coordinates): + assert ROOT.Math.Polar3DVector(*constructor1).Dot( + ROOT.Math.Polar3DVector(*constructor2) + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor1))), coordinates + )().dot( + getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor2))), + coordinates, + )() + ) + ) + + +# Run a test that compares ROOT's 'Mag2()' with vector's 'rho2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mag2(constructor, coordinates): + assert ROOT.Math.Polar3DVector(*constructor).Mag2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )().rho2 + ) + + +# Run a test that compares ROOT's 'R()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_R(constructor, coordinates): + assert ROOT.Math.Polar3DVector(*constructor).R() == pytest.approx( + np.sqrt( + getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), + coordinates, + )().rho2 + ) + ) + + +# Run a test that compares ROOT's 'Phi()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Phi(constructor, coordinates): + assert ROOT.Math.Polar3DVector(*constructor).Phi() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )().phi + ) + + +# Run a test that compares ROOT's 'RotateX()' with vector's 'rotateX' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateX(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationX(angle) * ROOT.Math.Polar3DVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )() + res_vec = vec.rotateX(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'RotateY()' with vector's 'rotateY' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateY(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationY(angle) * ROOT.Math.Polar3DVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )() + res_vec = vec.rotateY(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'RotateZ()' with vector's 'rotateZ' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateZ(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationZ(angle) * ROOT.Math.Polar3DVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )() + res_vec = vec.rotateZ(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'Unit()' with vector's 'unit' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Unit(constructor, coordinates): + ref_vec = ROOT.Math.Polar3DVector(*constructor).Unit() + vec = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )() + res_vec = vec.unit + assert ref_vec.X() == pytest.approx(res_vec().x) + assert ref_vec.Y() == pytest.approx(res_vec().y) + assert ref_vec.Z() == pytest.approx(res_vec().z) + + +# Run a test that compares ROOT's 'X()' and 'Y()' with vector's 'x' and 'y' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_X_and_Y(constructor, coordinates): + vec = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )() + assert ROOT.Math.Polar3DVector(*constructor).X() == pytest.approx( + vec.x + ) and ROOT.Math.Polar3DVector(*constructor).Y() == pytest.approx(vec.y) + + +# Run a test that compares ROOT's '__add__' with vector's 'add' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_add(constructor, coordinates): + ref_vec = ROOT.Math.Polar3DVector(*constructor).__add__( + ROOT.Math.Polar3DVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )().add( + getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )() + ) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__sub__' with vector's 'subtract' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_sub(constructor, coordinates): + ref_vec = ROOT.Math.Polar3DVector(*constructor).__sub__( + ROOT.Math.Polar3DVector(*constructor) + ) + vec1 = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )() + vec2 = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )() + res_vec = vec1.subtract(vec2) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's '__neg__' with vector's '__neg__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_neg(constructor, coordinates): + ref_vec = ROOT.Math.Polar3DVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )().__neg__ + assert ref_vec.X() == pytest.approx(vec().x) + assert ref_vec.Y() == pytest.approx(vec().y) + assert ref_vec.Z() == pytest.approx(vec().z) + + +# Run a test that compares ROOT's '__mul__' with vector's 'mul' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.Polar3DVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__truediv__' with vector's '__truediv__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.Polar3DVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__eq__' with vector's 'isclose' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_eq(constructor, coordinates): + ref_vec = ROOT.Math.Polar3DVector(*constructor).__eq__( + ROOT.Math.Polar3DVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )().isclose( + getattr( + vector.obj(**dict(zip(["rho", "theta", "phi"], constructor))), coordinates + )() + ) + assert ref_vec == vec diff --git a/tests/root/test_PtEtaPhiEVector.py b/tests/root/test_PtEtaPhiEVector.py new file mode 100644 index 00000000..f3b276b4 --- /dev/null +++ b/tests/root/test_PtEtaPhiEVector.py @@ -0,0 +1,561 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.PtEtaPhiEVector constructor arguments to get all the weird cases. +constructor = [ + (0, 0, 0, 0), + (0, 0, 1, 0), # theta == 0.0 + (0, 0, -1, 0), + (0, 0, 1, 0), + (0, 0, 0, 4294967296), + (0, 4294967296, 0, 0), + (0, 0, 0, 10), + (0, 0, 0, -10), + (1, 2, 3, 0), + (1, 2, 3, 10), + (1, 2, 3, -10), + (1.0, 2.0, 3.0, 2.5), + (1, 2, 3, 2.5), + (1, 2, 3, -2.5), +] + +# Coordinate conversion methods to apply to the VectorObject4D. +coordinate_list = [ + "to_xyzt", + "to_xythetat", # may fail for constructor2 + "to_xyetat", + "to_rhophizt", + "to_rhophithetat", + "to_rhophietat", + "to_xyztau", + "to_xythetatau", + "to_xyetatau", + "to_rhophiztau", + "to_rhophithetatau", + "to_rhophietatau", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param + + +# Run a test that compares ROOT's 'Dot()' with vector's 'dot' for all cases. +# Dot +@pytest.mark.parametrize("constructor", constructor) +def test_Dot(constructor, coordinates): + v1 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )() + v2 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )() + assert ROOT.Math.PtEtaPhiEVector(*constructor).Dot( + ROOT.Math.PtEtaPhiEVector(*constructor) + ) == pytest.approx(v1.dot(v2)) + + +# Run the same test within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fizz_Dot(constructor1, constructor2, coordinates): + v1 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor1))), coordinates + )() + v2 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor2))), coordinates + )() + assert ROOT.Math.PtEtaPhiEVector(*constructor1).Dot( + ROOT.Math.PtEtaPhiEVector(*constructor2) + ) == pytest.approx(v1.dot(v2)) + + +# Run a test that compares ROOT's 'M2()' with vector's 'tau2' for all cases. +# Mass2 is our tau2 (or mass2 if it's a momentum vector and has kinematic synonyms) +@pytest.mark.parametrize("constructor", constructor) +def test_M2(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).M2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().tau2 + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_M2(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).M2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().tau2 + ) + + +# Run a test that compares ROOT's 'M()' with vector's 'tau' for all cases. +# Mass is tau (or mass) +@pytest.mark.parametrize("constructor", constructor) +def test_M(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).M() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().tau + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_M(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).M() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().tau + ) + + +# Run a test that compares ROOT's 'Mt2()' with vector's 'mt2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mt2(constructor, coordinates): + v = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )() + assert ROOT.Math.PtEtaPhiEVector(*constructor).Mt2() == pytest.approx( + v.t * v.t - v.z * v.z + ) + + +# Run a test that compares ROOT's 'Mt()' with vector's 'mt' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mt(constructor, coordinates): + v = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )() + assert ROOT.Math.PtEtaPhiEVector(*constructor).mt() == pytest.approx( + v.lib.sqrt(v.t * v.t - v.z * v.z) + ) + + +# Run a test that compares ROOT's 'P2()' with vector's 'mag2' for all cases. +# P2 is our mag2 (ROOT's 4D mag2 is the dot product with itself, what we call tau or mass) +@pytest.mark.parametrize("constructor", constructor) +def test_P2(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).P2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().mag2 + ) + + +# Run a test that compares ROOT's 'P()' with vector's 'mag' for all cases. +# P is our mag (same deal) +@pytest.mark.parametrize("constructor", constructor) +def test_P(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).P() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().mag + ) + + +# Run a test that compares ROOT's 'Perp2()' with vector's 'rho2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Perp2(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).Perp2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().rho2 + ) + + +# Run a test that compares ROOT's 'Perp()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Perp(constructor, coordinates): + assert ROOT.Math.sqrt( + ROOT.Math.PtEtaPhiEVector(*constructor).Perp2() + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().rho + ) + + +# Run a test that compares ROOT's 'Phi()' with vector's 'phi' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Phi(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).Phi() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().phi + ) + + +# Run a test that compares ROOT's 'Rapidity()' with vector's 'rapidity' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Rapidity(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).Rapidity() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().rapidity + ) + + +# Run a test that compares ROOT's 'Beta()' with vector's 'beta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Beta(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).Beta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().beta + ) + + +# Run a test that compares ROOT's 'Eta()' with vector's 'eta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Eta(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).Eta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().eta + ) + + +# Run a test that compares ROOT's 'Gamma()' with vector's 'gamma' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Gamma(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).Gamma() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().gamma + ) + + +# Run a test that compares ROOT's 'isLightlike()' with vector's 'is_lightlike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isLightlike(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).isLightlike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().is_lightlike() + ) + + +# Run a test that compares ROOT's 'isSpacelike()' with vector's 'is_spacelike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isSpacelike(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).isSpacelike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().is_spacelike() + ) + + +# Run a test that compares ROOT's 'isTimelike()' with vector's 'is_timelike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isTimelike(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).isTimelike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().is_timelike() + ) + + +# Run a test that compares ROOT's 'Theta()' with vector's 'theta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Theta(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).Theta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().theta + ) + + +# Run a test that compares ROOT's 'X()' with vector's 'x' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_X(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).X() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().x + ) + + +# Run a test that compares ROOT's 'Y()' with vector's 'y' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Y(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).Y() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().y + ) + + +# Run a test that compares ROOT's 'Z()' with vector's 'z' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Z(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).Z() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().z + ) + + +# Run a test that compares ROOT's 'T()' with vector's 't' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_T(constructor, coordinates): + assert ROOT.Math.PtEtaPhiEVector(*constructor).T() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )().t + ) + + +# Run a test that compares ROOT's '__add__' with vector's 'add' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_add(constructor, coordinates): + ref_vec = ROOT.Math.PtEtaPhiEVector(*constructor).__add__( + ROOT.Math.PtEtaPhiEVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )().add( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )() + ) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__sub__' with vector's 'subtract' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_sub(constructor, coordinates): + ref_vec = ROOT.Math.PtEtaPhiEVector(*constructor).__sub__( + ROOT.Math.PtEtaPhiEVector(*constructor) + ) + vec1 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )() + vec2 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )() + res_vec = vec1.subtract(vec2) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's '__neg__' with vector's '__neg__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_neg(constructor, coordinates): + ref_vec = ROOT.Math.PtEtaPhiEVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )().__neg__ + assert ref_vec.X() == pytest.approx(vec().x) + assert ref_vec.Y() == pytest.approx(vec().y) + assert ref_vec.Z() == pytest.approx(vec().z) + assert ref_vec.T() == pytest.approx(vec().t) + + +# Run a test that compares ROOT's '__mul__' with vector's 'mul' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.PtEtaPhiEVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__truediv__' with vector's '__truediv__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.PtEtaPhiEVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__eq__' with vector's 'isclose' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_eq(constructor, coordinates): + ref_vec = ROOT.Math.PtEtaPhiEVector(*constructor).__eq__( + ROOT.Math.PtEtaPhiEVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )().isclose( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), + coordinates, + )() + ) + assert ref_vec == vec + + +# Run a test that compares ROOT's 'RotateX()' with vector's 'rotateX' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateX(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationX(angle) * ROOT.Math.PtEtaPhiEVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )() + res_vec = vec.rotateX(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's 'RotateY()' with vector's 'rotateY' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateY(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationY(angle) * ROOT.Math.PtEtaPhiEVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )() + res_vec = vec.rotateY(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's 'RotateZ()' with vector's 'rotateZ' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateZ(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationZ(angle) * ROOT.Math.PtEtaPhiEVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "t"], constructor))), coordinates + )() + res_vec = vec.rotateZ(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) diff --git a/tests/root/test_PtEtaPhiMVector.py b/tests/root/test_PtEtaPhiMVector.py new file mode 100644 index 00000000..6d70713c --- /dev/null +++ b/tests/root/test_PtEtaPhiMVector.py @@ -0,0 +1,561 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.PtEtaPhiMVector constructor arguments to get all the weird cases. +constructor = [ + (0, 0, 0, 0), + (0, 0, 1, 0), # theta == 0.0 + (0, 0, -1, 0), + (0, 0, 1, 0), + (0, 0, 0, 4294967296), + (0, 4294967296, 0, 0), + (0, 0, 0, 10), + (0, 0, 0, -10), + (1, 2, 3, 0), + (1, 2, 3, 10), + (1, 2, 3, -10), + (1.0, 2.0, 3.0, 2.5), + (1, 2, 3, 2.5), + (1, 2, 3, -2.5), +] + +# Coordinate conversion methods to apply to the VectorObject4D. +coordinate_list = [ + "to_xyzt", + "to_xythetat", # may fail for constructor2 + "to_xyetat", + "to_rhophizt", + "to_rhophithetat", + "to_rhophietat", + "to_xyztau", + "to_xythetatau", + "to_xyetatau", + "to_rhophiztau", + "to_rhophithetatau", + "to_rhophietatau", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param + + +# Run a test that compares ROOT's 'Dot()' with vector's 'dot' for all cases. +# Dot +@pytest.mark.parametrize("constructor", constructor) +def test_Dot(constructor, coordinates): + v1 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )() + v2 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )() + assert ROOT.Math.PtEtaPhiMVector(*constructor).Dot( + ROOT.Math.PtEtaPhiMVector(*constructor) + ) == pytest.approx(v1.dot(v2)) + + +# Run the same test within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fizz_Dot(constructor1, constructor2, coordinates): + v1 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor1))), coordinates + )() + v2 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor2))), coordinates + )() + assert ROOT.Math.PtEtaPhiMVector(*constructor1).Dot( + ROOT.Math.PtEtaPhiMVector(*constructor2) + ) == pytest.approx(v1.dot(v2)) + + +# Run a test that compares ROOT's 'M2()' with vector's 'tau2' for all cases. +# Mass2 is our tau2 (or mass2 if it's a momentum vector and has kinematic synonyms) +@pytest.mark.parametrize("constructor", constructor) +def test_M2(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).M2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().tau2 + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_M2(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).M2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().tau2 + ) + + +# Run a test that compares ROOT's 'M()' with vector's 'tau' for all cases. +# Mass is tau (or mass) +@pytest.mark.parametrize("constructor", constructor) +def test_M(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).M() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().tau + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_M(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).M() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().tau + ) + + +# Run a test that compares ROOT's 'Mt2()' with vector's 'mt2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mt2(constructor, coordinates): + v = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )() + assert ROOT.Math.PtEtaPhiMVector(*constructor).Mt2() == pytest.approx( + v.t * v.t - v.z * v.z + ) + + +# Run a test that compares ROOT's 'Mt()' with vector's 'mt' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mt(constructor, coordinates): + v = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )() + assert ROOT.Math.PtEtaPhiMVector(*constructor).mt() == pytest.approx( + v.lib.sqrt(v.t * v.t - v.z * v.z) + ) + + +# Run a test that compares ROOT's 'P2()' with vector's 'mag2' for all cases. +# P2 is our mag2 (ROOT's 4D mag2 is the dot product with itself, what we call tau or mass) +@pytest.mark.parametrize("constructor", constructor) +def test_P2(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).P2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().mag2 + ) + + +# Run a test that compares ROOT's 'P()' with vector's 'mag' for all cases. +# P is our mag (same deal) +@pytest.mark.parametrize("constructor", constructor) +def test_P(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).P() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().mag + ) + + +# Run a test that compares ROOT's 'Perp2()' with vector's 'rho2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Perp2(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).Perp2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().rho2 + ) + + +# Run a test that compares ROOT's 'Perp()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Perp(constructor, coordinates): + assert ROOT.Math.sqrt( + ROOT.Math.PtEtaPhiMVector(*constructor).Perp2() + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().rho + ) + + +# Run a test that compares ROOT's 'Phi()' with vector's 'phi' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Phi(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).Phi() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().phi + ) + + +# Run a test that compares ROOT's 'Rapidity()' with vector's 'rapidity' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Rapidity(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).Rapidity() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().rapidity + ) + + +# Run a test that compares ROOT's 'Beta()' with vector's 'beta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Beta(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).Beta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().beta + ) + + +# Run a test that compares ROOT's 'Eta()' with vector's 'eta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Eta(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).Eta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().eta + ) + + +# Run a test that compares ROOT's 'Gamma()' with vector's 'gamma' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Gamma(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).Gamma() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().gamma + ) + + +# Run a test that compares ROOT's 'isLightlike()' with vector's 'is_lightlike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isLightlike(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).isLightlike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().is_lightlike() + ) + + +# Run a test that compares ROOT's 'isSpacelike()' with vector's 'is_spacelike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isSpacelike(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).isSpacelike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().is_spacelike() + ) + + +# Run a test that compares ROOT's 'isTimelike()' with vector's 'is_timelike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isTimelike(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).isTimelike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().is_timelike() + ) + + +# Run a test that compares ROOT's 'Theta()' with vector's 'theta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Theta(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).Theta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().theta + ) + + +# Run a test that compares ROOT's 'X()' with vector's 'x' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_X(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).X() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().x + ) + + +# Run a test that compares ROOT's 'Y()' with vector's 'y' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Y(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).Y() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().y + ) + + +# Run a test that compares ROOT's 'Z()' with vector's 'z' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Z(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).Z() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().z + ) + + +# Run a test that compares ROOT's 'T()' with vector's 't' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_T(constructor, coordinates): + assert ROOT.Math.PtEtaPhiMVector(*constructor).T() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )().t + ) + + +# Run a test that compares ROOT's '__add__' with vector's 'add' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_add(constructor, coordinates): + ref_vec = ROOT.Math.PtEtaPhiMVector(*constructor).__add__( + ROOT.Math.PtEtaPhiMVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )().add( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )() + ) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__sub__' with vector's 'subtract' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_sub(constructor, coordinates): + ref_vec = ROOT.Math.PtEtaPhiMVector(*constructor).__sub__( + ROOT.Math.PtEtaPhiMVector(*constructor) + ) + vec1 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )() + vec2 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )() + res_vec = vec1.subtract(vec2) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's '__neg__' with vector's '__neg__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_neg(constructor, coordinates): + ref_vec = ROOT.Math.PtEtaPhiMVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )().__neg__ + assert ref_vec.X() == pytest.approx(vec().x) + assert ref_vec.Y() == pytest.approx(vec().y) + assert ref_vec.Z() == pytest.approx(vec().z) + assert ref_vec.T() == pytest.approx(vec().t) + + +# Run a test that compares ROOT's '__mul__' with vector's 'mul' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.PtEtaPhiMVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__truediv__' with vector's '__truediv__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.PtEtaPhiMVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__eq__' with vector's 'isclose' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_eq(constructor, coordinates): + ref_vec = ROOT.Math.PtEtaPhiMVector(*constructor).__eq__( + ROOT.Math.PtEtaPhiMVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )().isclose( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), + coordinates, + )() + ) + assert ref_vec == vec + + +# Run a test that compares ROOT's 'RotateX()' with vector's 'rotateX' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateX(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationX(angle) * ROOT.Math.PtEtaPhiMVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )() + res_vec = vec.rotateX(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's 'RotateY()' with vector's 'rotateY' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateY(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationY(angle) * ROOT.Math.PtEtaPhiMVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )() + res_vec = vec.rotateY(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's 'RotateZ()' with vector's 'rotateZ' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateZ(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationZ(angle) * ROOT.Math.PtEtaPhiMVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi", "tau"], constructor))), coordinates + )() + res_vec = vec.rotateZ(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) diff --git a/tests/root/test_PxPyPzEVector.py b/tests/root/test_PxPyPzEVector.py new file mode 100644 index 00000000..f22659bf --- /dev/null +++ b/tests/root/test_PxPyPzEVector.py @@ -0,0 +1,538 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.PxPyPzEVector constructor arguments to get all the weird cases. +constructor = [ + (0, 0, 0, 0), + (0, 0, 1, 0), # theta == 0.0 + (0, 0, -1, 0), + (0, 0, 1, 0), + (0, 0, 0, 4294967296), + (0, 4294967296, 0, 0), + (0, 0, 0, 10), + (0, 0, 0, -10), + (1, 2, 3, 0), + (1, 2, 3, 10), + (1, 2, 3, -10), + (1.0, 2.0, 3.0, 2.5), + (1, 2, 3, 2.5), + (1, 2, 3, -2.5), +] + +# Coordinate conversion methods to apply to the VectorObject4D. +coordinate_list = [ + "to_xyzt", + "to_xythetat", # may fail for constructor2 + "to_xyetat", + "to_rhophizt", + "to_rhophithetat", + "to_rhophietat", + "to_xyztau", + "to_xythetatau", + "to_xyetatau", + "to_rhophiztau", + "to_rhophithetatau", + "to_rhophietatau", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param + + +# Run a test that compares ROOT's 'Dot()' with vector's 'dot' for all cases. +# Dot +@pytest.mark.parametrize("constructor", constructor) +def test_Dot(constructor, coordinates): + v1 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + v2 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + assert ROOT.Math.PxPyPzEVector(*constructor).Dot( + ROOT.Math.PxPyPzEVector(*constructor) + ) == pytest.approx(v1.dot(v2)) + + +# Run the same test within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fizz_Dot(constructor1, constructor2, coordinates): + v1 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor1))), coordinates + )() + v2 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor2))), coordinates + )() + assert ROOT.Math.PxPyPzEVector(*constructor1).Dot( + ROOT.Math.PxPyPzEVector(*constructor2) + ) == pytest.approx(v1.dot(v2)) + + +# Run a test that compares ROOT's 'M2()' with vector's 'tau2' for all cases. +# Mass2 is our tau2 (or mass2 if it's a momentum vector and has kinematic synonyms) +@pytest.mark.parametrize("constructor", constructor) +def test_M2(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).M2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().tau2 + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_M2(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).M2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().tau2 + ) + + +# Run a test that compares ROOT's 'M()' with vector's 'tau' for all cases. +# Mass is tau (or mass) +@pytest.mark.parametrize("constructor", constructor) +def test_M(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).M() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().tau + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_M(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).M() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().tau + ) + + +# Run a test that compares ROOT's 'Mt2()' with vector's 'mt2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mt2(constructor, coordinates): + v = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + assert ROOT.Math.PxPyPzEVector(*constructor).Mt2() == pytest.approx( + v.t * v.t - v.z * v.z + ) + + +# Run a test that compares ROOT's 'Mt()' with vector's 'mt' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mt(constructor, coordinates): + v = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + assert ROOT.Math.PxPyPzEVector(*constructor).mt() == pytest.approx( + v.lib.sqrt(v.t * v.t - v.z * v.z) + ) + + +# Run a test that compares ROOT's 'P2()' with vector's 'mag2' for all cases. +# P2 is our mag2 (ROOT's 4D mag2 is the dot product with itself, what we call tau or mass) +@pytest.mark.parametrize("constructor", constructor) +def test_P2(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).P2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().mag2 + ) + + +# Run a test that compares ROOT's 'P()' with vector's 'mag' for all cases. +# P is our mag (same deal) +@pytest.mark.parametrize("constructor", constructor) +def test_P(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).P() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().mag + ) + + +# Run a test that compares ROOT's 'Perp2()' with vector's 'rho2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Perp2(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).Perp2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().rho2 + ) + + +# Run a test that compares ROOT's 'Perp()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Perp(constructor, coordinates): + assert ROOT.Math.sqrt( + ROOT.Math.PxPyPzEVector(*constructor).Perp2() + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().rho + ) + + +# Run a test that compares ROOT's 'Phi()' with vector's 'phi' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Phi(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).Phi() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().phi + ) + + +# Run a test that compares ROOT's 'Rapidity()' with vector's 'rapidity' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Rapidity(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).Rapidity() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().rapidity + ) + + +# Run a test that compares ROOT's 'Beta()' with vector's 'beta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Beta(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).Beta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().beta + ) + + +# Run a test that compares ROOT's 'Eta()' with vector's 'eta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Eta(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).Eta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().eta + ) + + +# Run a test that compares ROOT's 'Gamma()' with vector's 'gamma' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Gamma(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).Gamma() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().gamma + ) + + +# Run a test that compares ROOT's 'isLightlike()' with vector's 'is_lightlike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isLightlike(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).isLightlike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().is_lightlike() + ) + + +# Run a test that compares ROOT's 'isSpacelike()' with vector's 'is_spacelike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isSpacelike(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).isSpacelike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().is_spacelike() + ) + + +# Run a test that compares ROOT's 'isTimelike()' with vector's 'is_timelike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isTimelike(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).isTimelike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().is_timelike() + ) + + +# Run a test that compares ROOT's 'Theta()' with vector's 'theta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Theta(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).Theta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().theta + ) + + +# Run a test that compares ROOT's 'X()' with vector's 'x' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_X(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).X() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().x + ) + + +# Run a test that compares ROOT's 'Y()' with vector's 'y' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Y(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).Y() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().y + ) + + +# Run a test that compares ROOT's 'Z()' with vector's 'z' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Z(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).Z() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().z + ) + + +# Run a test that compares ROOT's 'T()' with vector's 't' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_T(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).T() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().t + ) + + +# Run a test that compares ROOT's '__add__' with vector's 'add' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_add(constructor, coordinates): + ref_vec = ROOT.Math.PxPyPzEVector(*constructor).__add__( + ROOT.Math.PxPyPzEVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().add( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + ) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__sub__' with vector's 'subtract' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_sub(constructor, coordinates): + ref_vec = ROOT.Math.PxPyPzEVector(*constructor).__sub__( + ROOT.Math.PxPyPzEVector(*constructor) + ) + vec1 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + vec2 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + res_vec = vec1.subtract(vec2) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's '__neg__' with vector's '__neg__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_neg(constructor, coordinates): + ref_vec = ROOT.Math.PxPyPzEVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().__neg__ + assert ref_vec.X() == pytest.approx(vec().x) + assert ref_vec.Y() == pytest.approx(vec().y) + assert ref_vec.Z() == pytest.approx(vec().z) + assert ref_vec.T() == pytest.approx(vec().t) + + +# Run a test that compares ROOT's '__mul__' with vector's 'mul' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.PxPyPzEVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__truediv__' with vector's '__truediv__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.PxPyPzEVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__eq__' with vector's 'isclose' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_eq(constructor, coordinates): + ref_vec = ROOT.Math.PxPyPzEVector(*constructor).__eq__( + ROOT.Math.PxPyPzEVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().isclose( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + ) + assert ref_vec == vec + + +# Run a test that compares ROOT's 'RotateX()' with vector's 'rotateX' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateX(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationX(angle) * ROOT.Math.PxPyPzEVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + res_vec = vec.rotateX(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's 'RotateY()' with vector's 'rotateY' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateY(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationY(angle) * ROOT.Math.PxPyPzEVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + res_vec = vec.rotateY(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's 'RotateZ()' with vector's 'rotateZ' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateZ(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationZ(angle) * ROOT.Math.PxPyPzEVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )() + res_vec = vec.rotateZ(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) diff --git a/tests/root/test_PxPyPzMVector.py b/tests/root/test_PxPyPzMVector.py new file mode 100644 index 00000000..ee545c06 --- /dev/null +++ b/tests/root/test_PxPyPzMVector.py @@ -0,0 +1,538 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.PxPyPzMVector constructor arguments to get all the weird cases. +constructor = [ + (0, 0, 0, 0), + (0, 0, 1, 0), # theta == 0.0 + (0, 0, -1, 0), + (0, 0, 1, 0), + (0, 0, 0, 4294967296), + (0, 4294967296, 0, 0), + (0, 0, 0, 10), + (0, 0, 0, -10), + (1, 2, 3, 0), + (1, 2, 3, 10), + (1, 2, 3, -10), + (1.0, 2.0, 3.0, 2.5), + (1, 2, 3, 2.5), + (1, 2, 3, -2.5), +] + +# Coordinate conversion methods to apply to the VectorObject4D. +coordinate_list = [ + "to_xyzt", + "to_xythetat", # may fail for constructor2 + "to_xyetat", + "to_rhophizt", + "to_rhophithetat", + "to_rhophietat", + "to_xyztau", + "to_xythetatau", + "to_xyetatau", + "to_rhophiztau", + "to_rhophithetatau", + "to_rhophietatau", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param + + +# Run a test that compares ROOT's 'Dot()' with vector's 'dot' for all cases. +# Dot +@pytest.mark.parametrize("constructor", constructor) +def test_Dot(constructor, coordinates): + v1 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + v2 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + assert ROOT.Math.PxPyPzMVector(*constructor).Dot( + ROOT.Math.PxPyPzMVector(*constructor) + ) == pytest.approx(v1.dot(v2)) + + +# Run the same test within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fizz_Dot(constructor1, constructor2, coordinates): + v1 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor1))), coordinates + )() + v2 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor2))), coordinates + )() + assert ROOT.Math.PxPyPzMVector(*constructor1).Dot( + ROOT.Math.PxPyPzMVector(*constructor2) + ) == pytest.approx(v1.dot(v2)) + + +# Run a test that compares ROOT's 'M2()' with vector's 'tau2' for all cases. +# Mass2 is our tau2 (or mass2 if it's a momentum vector and has kinematic synonyms) +@pytest.mark.parametrize("constructor", constructor) +def test_M2(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).M2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().tau2 + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_M2(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).M2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().tau2 + ) + + +# Run a test that compares ROOT's 'M()' with vector's 'tau' for all cases. +# Mass is tau (or mass) +@pytest.mark.parametrize("constructor", constructor) +def test_M(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).M() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().tau + ) + + +# Run the same tests within hypothesis +@given( + constructor=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ) +) +def test_fuzz_M(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).M() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().tau + ) + + +# Run a test that compares ROOT's 'Mt2()' with vector's 'mt2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mt2(constructor, coordinates): + v = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + assert ROOT.Math.PxPyPzMVector(*constructor).Mt2() == pytest.approx( + v.t * v.t - v.z * v.z + ) + + +# Run a test that compares ROOT's 'Mt()' with vector's 'mt' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mt(constructor, coordinates): + v = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + assert ROOT.Math.PxPyPzMVector(*constructor).mt() == pytest.approx( + v.lib.sqrt(v.t * v.t - v.z * v.z) + ) + + +# Run a test that compares ROOT's 'P2()' with vector's 'mag2' for all cases. +# P2 is our mag2 (ROOT's 4D mag2 is the dot product with itself, what we call tau or mass) +@pytest.mark.parametrize("constructor", constructor) +def test_P2(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).P2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().mag2 + ) + + +# Run a test that compares ROOT's 'P()' with vector's 'mag' for all cases. +# P is our mag (same deal) +@pytest.mark.parametrize("constructor", constructor) +def test_P(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).P() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().mag + ) + + +# Run a test that compares ROOT's 'Perp2()' with vector's 'rho2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Perp2(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).Perp2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().rho2 + ) + + +# Run a test that compares ROOT's 'Perp()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Perp(constructor, coordinates): + assert ROOT.Math.sqrt( + ROOT.Math.PxPyPzMVector(*constructor).Perp2() + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().rho + ) + + +# Run a test that compares ROOT's 'Phi()' with vector's 'phi' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Phi(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).Phi() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().phi + ) + + +# Run a test that compares ROOT's 'Rapidity()' with vector's 'rapidity' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Rapidity(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).Rapidity() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().rapidity + ) + + +# Run a test that compares ROOT's 'Beta()' with vector's 'beta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Beta(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).Beta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().beta + ) + + +# Run a test that compares ROOT's 'Eta()' with vector's 'eta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Eta(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).Eta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().eta + ) + + +# Run a test that compares ROOT's 'Gamma()' with vector's 'gamma' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Gamma(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).Gamma() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().gamma + ) + + +# Run a test that compares ROOT's 'isLightlike()' with vector's 'is_lightlike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isLightlike(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).isLightlike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().is_lightlike() + ) + + +# Run a test that compares ROOT's 'isSpacelike()' with vector's 'is_spacelike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isSpacelike(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).isSpacelike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().is_spacelike() + ) + + +# Run a test that compares ROOT's 'isTimelike()' with vector's 'is_timelike' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_isTimelike(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).isTimelike() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().is_timelike() + ) + + +# Run a test that compares ROOT's 'Theta()' with vector's 'theta' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Theta(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).Theta() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().theta + ) + + +# Run a test that compares ROOT's 'X()' with vector's 'x' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_X(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).X() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().x + ) + + +# Run a test that compares ROOT's 'Y()' with vector's 'y' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Y(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).Y() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().y + ) + + +# Run a test that compares ROOT's 'Z()' with vector's 'z' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Z(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).Z() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().z + ) + + +# Run a test that compares ROOT's 'T()' with vector's 't' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_T(constructor, coordinates): + assert ROOT.Math.PxPyPzMVector(*constructor).T() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().t + ) + + +# Run a test that compares ROOT's '__add__' with vector's 'add' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_add(constructor, coordinates): + ref_vec = ROOT.Math.PxPyPzMVector(*constructor).__add__( + ROOT.Math.PxPyPzMVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().add( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + ) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__sub__' with vector's 'subtract' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_sub(constructor, coordinates): + ref_vec = ROOT.Math.PxPyPzMVector(*constructor).__sub__( + ROOT.Math.PxPyPzMVector(*constructor) + ) + vec1 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + vec2 = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + res_vec = vec1.subtract(vec2) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's '__neg__' with vector's '__neg__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_neg(constructor, coordinates): + ref_vec = ROOT.Math.PxPyPzMVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().__neg__ + assert ref_vec.X() == pytest.approx(vec().x) + assert ref_vec.Y() == pytest.approx(vec().y) + assert ref_vec.Z() == pytest.approx(vec().z) + assert ref_vec.T() == pytest.approx(vec().t) + + +# Run a test that compares ROOT's '__mul__' with vector's 'mul' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.PxPyPzMVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__truediv__' with vector's '__truediv__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.PxPyPzMVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + assert ref_vec.T() == pytest.approx(vec.t) + + +# Run a test that compares ROOT's '__eq__' with vector's 'isclose' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_eq(constructor, coordinates): + ref_vec = ROOT.Math.PxPyPzMVector(*constructor).__eq__( + ROOT.Math.PxPyPzMVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )().isclose( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + ) + assert ref_vec == vec + + +# Run a test that compares ROOT's 'RotateX()' with vector's 'rotateX' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateX(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationX(angle) * ROOT.Math.PxPyPzMVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + res_vec = vec.rotateX(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's 'RotateY()' with vector's 'rotateY' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateY(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationY(angle) * ROOT.Math.PxPyPzMVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + res_vec = vec.rotateY(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) + + +# Run a test that compares ROOT's 'RotateZ()' with vector's 'rotateZ' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateZ(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationZ(angle) * ROOT.Math.PxPyPzMVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z", "tau"], constructor))), coordinates + )() + res_vec = vec.rotateZ(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + assert ref_vec.T() == pytest.approx(res_vec.t) diff --git a/tests/root/test_Quaternion.py b/tests/root/test_Quaternion.py new file mode 100644 index 00000000..6dbe90a4 --- /dev/null +++ b/tests/root/test_Quaternion.py @@ -0,0 +1,85 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.XYVector constructor arguments to get all the weird cases. +constructor = [ + (0, 0, 0, 0), + (0, 0, 1, 0), # theta == 0.0 + (0, 0, -1, 0), + (0, 0, 1, 0), + (0, 0, 0, 4294967296), + (0, 4294967296, 0, 0), + (0, 0, 0, 10), + (0, 0, 0, -10), + (1, 2, 3, 0), + (1, 2, 3, 10), + (1, 2, 3, -10), + (1.0, 2.0, 3.0, 2.5), + (1, 2, 3, 2.5), + (1, 2, 3, -2.5), +] + +# Coordinate conversion methods to apply to the VectorObject4D. +coordinate_list = [ + "to_xyzt", + "to_xythetat", # may fail for constructor2 + "to_xyetat", + "to_rhophizt", + "to_rhophithetat", + "to_rhophietat", + "to_xyztau", + "to_xythetatau", + "to_xyetatau", + "to_rhophiztau", + "to_rhophithetatau", + "to_rhophietatau", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param diff --git a/tests/root/test_RhoEtaPhiVector.py b/tests/root/test_RhoEtaPhiVector.py new file mode 100644 index 00000000..59640cb0 --- /dev/null +++ b/tests/root/test_RhoEtaPhiVector.py @@ -0,0 +1,308 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import numpy as np +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.RhoEtaPhiVector constructor arguments to get all the weird cases. +constructor = [ + (0, 0, 0), + (0, 10, 0), + (0, -10, 0), + (1, 0, 0), + (1, 10, 0), + (1, -10, 0), + (1.0, 2.5, 2.0), + (1, 2.5, 2.0), + (1, -2.5, 2.0), +] + +# Coordinate conversion methods to apply to the VectorObject2D. +coordinate_list = [ + "to_xyz", + "to_rhophieta", + "to_rhophitheta", + "to_rhophiz", + "to_xyeta", + "to_xytheta", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param + + +# Run a test that compares ROOT's 'Dot()' with vector's 'dot' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Dot(constructor, coordinates): + assert ROOT.Math.RhoEtaPhiVector(*constructor).Dot( + ROOT.Math.RhoEtaPhiVector(*constructor) + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )().dot( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )() + ) + ) + + +# Run the same tests within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fuzz_Dot(constructor1, constructor2, coordinates): + assert ROOT.Math.RhoEtaPhiVector(*constructor1).Dot( + ROOT.Math.RhoEtaPhiVector(*constructor2) + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor1))), coordinates + )().dot( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor2))), + coordinates, + )() + ) + ) + + +# Run a test that compares ROOT's 'Mag2()' with vector's 'rho2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mag2(constructor, coordinates): + assert ROOT.Math.RhoEtaPhiVector(*constructor).Mag2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )().rho2 + ) + + +# Run a test that compares ROOT's 'R()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_R(constructor, coordinates): + assert ROOT.Math.RhoEtaPhiVector(*constructor).R() == pytest.approx( + np.sqrt( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )().rho2 + ) + ) + + +# Run a test that compares ROOT's 'Phi()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Phi(constructor, coordinates): + assert ROOT.Math.RhoEtaPhiVector(*constructor).Phi() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )().phi + ) + + +# Run a test that compares ROOT's 'RotateX()' with vector's 'rotateX' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateX(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationX(angle) * ROOT.Math.RhoEtaPhiVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )() + res_vec = vec.rotateX(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'RotateY()' with vector's 'rotateY' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateY(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationY(angle) * ROOT.Math.RhoEtaPhiVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )() + res_vec = vec.rotateY(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'RotateZ()' with vector's 'rotateZ' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateZ(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationZ(angle) * ROOT.Math.RhoEtaPhiVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )() + res_vec = vec.rotateZ(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'Unit()' with vector's 'unit' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Unit(constructor, coordinates): + ref_vec = ROOT.Math.RhoEtaPhiVector(*constructor).Unit() + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )() + res_vec = vec.unit + assert ref_vec.X() == pytest.approx(res_vec().x) + assert ref_vec.Y() == pytest.approx(res_vec().y) + assert ref_vec.Z() == pytest.approx(res_vec().z) + + +# Run a test that compares ROOT's 'X()' and 'Y()' with vector's 'x' and 'y' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_X_and_Y(constructor, coordinates): + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )() + assert ROOT.Math.RhoEtaPhiVector(*constructor).X() == pytest.approx( + vec.x + ) and ROOT.Math.RhoEtaPhiVector(*constructor).Y() == pytest.approx(vec.y) + + +# Run a test that compares ROOT's '__add__' with vector's 'add' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_add(constructor, coordinates): + ref_vec = ROOT.Math.RhoEtaPhiVector(*constructor).__add__( + ROOT.Math.RhoEtaPhiVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )().add( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )() + ) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__sub__' with vector's 'subtract' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_sub(constructor, coordinates): + ref_vec = ROOT.Math.RhoEtaPhiVector(*constructor).__sub__( + ROOT.Math.RhoEtaPhiVector(*constructor) + ) + vec1 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )() + vec2 = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )() + res_vec = vec1.subtract(vec2) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's '__neg__' with vector's '__neg__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_neg(constructor, coordinates): + ref_vec = ROOT.Math.RhoEtaPhiVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )().__neg__ + assert ref_vec.X() == pytest.approx(vec().x) + assert ref_vec.Y() == pytest.approx(vec().y) + assert ref_vec.Z() == pytest.approx(vec().z) + + +# Run a test that compares ROOT's '__mul__' with vector's 'mul' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.RhoEtaPhiVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__truediv__' with vector's '__truediv__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.RhoEtaPhiVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__eq__' with vector's 'isclose' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_eq(constructor, coordinates): + ref_vec = ROOT.Math.RhoEtaPhiVector(*constructor).__eq__( + ROOT.Math.RhoEtaPhiVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )().isclose( + getattr( + vector.obj(**dict(zip(["rho", "eta", "phi"], constructor))), coordinates + )() + ) + assert ref_vec == vec diff --git a/tests/root/test_RhoZPhiVector.py b/tests/root/test_RhoZPhiVector.py new file mode 100644 index 00000000..7b491285 --- /dev/null +++ b/tests/root/test_RhoZPhiVector.py @@ -0,0 +1,307 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import numpy as np +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.RhoZPhiVector constructor arguments to get all the weird cases. +constructor = [ + (0, 0, 0), + (0, 10, 0), + (0, -10, 0), + (1, 0, 0), + (1, 10, 0), + (1, -10, 0), + (1.0, 2.5, 2.0), + (1, 2.5, 2.0), + (1, -2.5, 2.0), +] + +# Coordinate conversion methods to apply to the VectorObject2D. +coordinate_list = [ + "to_xyz", + "to_rhophieta", + "to_rhophitheta", + "to_rhophiz", + "to_xyeta", + "to_xytheta", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param + + +# Run a test that compares ROOT's 'Dot()' with vector's 'dot' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Dot(constructor, coordinates): + assert ROOT.Math.RhoZPhiVector(*constructor).Dot( + ROOT.Math.RhoZPhiVector(*constructor) + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )().dot( + getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )() + ) + ) + + +# Run the same tests within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fuzz_Dot(constructor1, constructor2, coordinates): + assert ROOT.Math.RhoZPhiVector(*constructor1).Dot( + ROOT.Math.RhoZPhiVector(*constructor2) + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor1))), coordinates + )().dot( + getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor2))), coordinates + )() + ) + ) + + +# Run a test that compares ROOT's 'Mag2()' with vector's 'rho2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mag2(constructor, coordinates): + assert ROOT.Math.RhoZPhiVector(*constructor).Mag2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )().rho2 + ) + + +# Run a test that compares ROOT's 'R()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_R(constructor, coordinates): + assert ROOT.Math.RhoZPhiVector(*constructor).R() == pytest.approx( + np.sqrt( + getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )().rho2 + ) + ) + + +# Run a test that compares ROOT's 'Phi()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Phi(constructor, coordinates): + assert ROOT.Math.RhoZPhiVector(*constructor).Phi() == pytest.approx( + getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )().phi + ) + + +# Run a test that compares ROOT's 'RotateX()' with vector's 'rotateX' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateX(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationX(angle) * ROOT.Math.RhoZPhiVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )() + res_vec = vec.rotateX(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'RotateY()' with vector's 'rotateY' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateY(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationY(angle) * ROOT.Math.RhoZPhiVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )() + res_vec = vec.rotateY(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'RotateZ()' with vector's 'rotateZ' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateZ(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationZ(angle) * ROOT.Math.RhoZPhiVector(*constructor) + vec = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )() + res_vec = vec.rotateZ(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'Unit()' with vector's 'unit' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Unit(constructor, coordinates): + ref_vec = ROOT.Math.RhoZPhiVector(*constructor).Unit() + vec = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )() + res_vec = vec.unit + assert ref_vec.X() == pytest.approx(res_vec().x) + assert ref_vec.Y() == pytest.approx(res_vec().y) + assert ref_vec.Z() == pytest.approx(res_vec().z) + + +# Run a test that compares ROOT's 'X()' and 'Y()' with vector's 'x' and 'y' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_X_and_Y(constructor, coordinates): + vec = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )() + assert ROOT.Math.RhoZPhiVector(*constructor).X() == pytest.approx( + vec.x + ) and ROOT.Math.RhoZPhiVector(*constructor).Y() == pytest.approx(vec.y) + + +# Run a test that compares ROOT's '__add__' with vector's 'add' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_add(constructor, coordinates): + ref_vec = ROOT.Math.RhoZPhiVector(*constructor).__add__( + ROOT.Math.RhoZPhiVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )().add( + getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )() + ) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__sub__' with vector's 'subtract' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_sub(constructor, coordinates): + ref_vec = ROOT.Math.RhoZPhiVector(*constructor).__sub__( + ROOT.Math.RhoZPhiVector(*constructor) + ) + vec1 = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )() + vec2 = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )() + res_vec = vec1.subtract(vec2) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's '__neg__' with vector's '__neg__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_neg(constructor, coordinates): + ref_vec = ROOT.Math.RhoZPhiVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )().__neg__ + assert ref_vec.X() == pytest.approx(vec().x) + assert ref_vec.Y() == pytest.approx(vec().y) + assert ref_vec.Z() == pytest.approx(vec().z) + + +# Run a test that compares ROOT's '__mul__' with vector's 'mul' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.RhoZPhiVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__truediv__' with vector's '__truediv__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.RhoZPhiVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__eq__' with vector's 'isclose' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_eq(constructor, coordinates): + ref_vec = ROOT.Math.RhoZPhiVector(*constructor).__eq__( + ROOT.Math.RhoZPhiVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )().isclose( + getattr( + vector.obj(**dict(zip(["rho", "z", "phi"], constructor))), coordinates + )() + ) + assert ref_vec == vec diff --git a/tests/root/test_XYVector.py b/tests/root/test_XYVector.py new file mode 100644 index 00000000..a84ff063 --- /dev/null +++ b/tests/root/test_XYVector.py @@ -0,0 +1,237 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import numpy as np +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.XYVector constructor arguments to get all the weird cases. +constructor = [ + (0, 0), + (0, 10), + (0, -10), + (1, 0), + (1, 10), + (1, -10), + (1.0, 2.5), + (1, 2.5), + (1, -2.5), +] + +# Coordinate conversion methods to apply to the VectorObject2D. +coordinate_list = [ + "to_xy", + "to_rhophi", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param + + +# Run a test that compares ROOT's 'Dot()' with vector's 'dot' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Dot(constructor, coordinates): + assert ROOT.Math.XYVector(*constructor).Dot( + ROOT.Math.XYVector(*constructor) + ) == pytest.approx( + getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)().dot( + getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)() + ) + ) + + +# Run the same tests within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fuzz_Dot(constructor1, constructor2, coordinates): + assert ROOT.Math.XYVector(*constructor1).Dot( + ROOT.Math.XYVector(*constructor2) + ) == pytest.approx( + getattr(vector.obj(**dict(zip(["x", "y"], constructor1))), coordinates)().dot( + getattr(vector.obj(**dict(zip(["x", "y"], constructor2))), coordinates)() + ) + ) + + +# Run a test that compares ROOT's 'Mag2()' with vector's 'rho2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mag2(constructor, coordinates): + assert ROOT.Math.XYVector(*constructor).Mag2() == pytest.approx( + getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)().rho2 + ) + + +# Run a test that compares ROOT's 'R()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_R(constructor, coordinates): + assert ROOT.Math.XYVector(*constructor).R() == pytest.approx( + np.sqrt( + getattr( + vector.obj(**dict(zip(["x", "y"], constructor))), coordinates + )().rho2 + ) + ) + + +# Run a test that compares ROOT's 'Phi()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Phi(constructor, coordinates): + assert ROOT.Math.XYVector(*constructor).Phi() == pytest.approx( + getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)().phi + ) + + +# Run a test that compares ROOT's 'Rotate()' with vector's 'rotateZ' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Rotate(constructor, angle, coordinates): + ref_vec = ROOT.Math.XYVector(*constructor) + ref_vec.Rotate(angle) + vec = getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)() + res_vec = vec.rotateZ(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + + +# Run a test that compares ROOT's 'Unit()' with vector's 'unit' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Unit(constructor, coordinates): + ref_vec = ROOT.Math.XYVector(*constructor).Unit() + vec = getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)() + res_vec = vec.unit + assert ref_vec.X() == pytest.approx(res_vec().x) + assert ref_vec.Y() == pytest.approx(res_vec().y) + + +# Run a test that compares ROOT's 'X()' and 'Y()' with vector's 'x' and 'y' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_X_and_Y(constructor, coordinates): + vec = getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)() + assert ROOT.Math.XYVector(*constructor).X() == pytest.approx( + vec.x + ) and ROOT.Math.XYVector(*constructor).Y() == pytest.approx(vec.y) + + +# Run a test that compares ROOT's '__add__' with vector's 'add' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_add(constructor, coordinates): + ref_vec = ROOT.Math.XYVector(*constructor).__add__(ROOT.Math.XYVector(*constructor)) + vec = getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)().add( + getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)() + ) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + + +# Run a test that compares ROOT's '__sub__' with vector's 'subtract' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_sub(constructor, coordinates): + ref_vec = ROOT.Math.XYVector(*constructor).__sub__(ROOT.Math.XYVector(*constructor)) + vec1 = getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)() + vec2 = getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)() + res_vec = vec1.subtract(vec2) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + + +# Run a test that compares ROOT's '__neg__' with vector's '__neg__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_neg(constructor, coordinates): + ref_vec = ROOT.Math.XYVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["x", "y"], constructor))), coordinates + )().__neg__ + assert ref_vec.X() == pytest.approx(vec().x) + assert ref_vec.Y() == pytest.approx(vec().y) + + +# Run a test that compares ROOT's '__mul__' with vector's 'mul' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.XYVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["x", "y"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + + +# Run a test that compares ROOT's '__truediv__' with vector's '__truediv__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.XYVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["x", "y"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + + +# Run a test that compares ROOT's '__eq__' with vector's 'isclose' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_eq(constructor, coordinates): + ref_vec = ROOT.Math.XYVector(*constructor).__eq__(ROOT.Math.XYVector(*constructor)) + vec = getattr( + vector.obj(**dict(zip(["x", "y"], constructor))), coordinates + )().isclose( + getattr(vector.obj(**dict(zip(["x", "y"], constructor))), coordinates)() + ) + assert ref_vec == vec diff --git a/tests/root/test_XYZVector.py b/tests/root/test_XYZVector.py new file mode 100644 index 00000000..7cd2880e --- /dev/null +++ b/tests/root/test_XYZVector.py @@ -0,0 +1,289 @@ +# Copyright (c) 2019-2021, Jonas Eschle, Jim Pivarski, Eduardo Rodrigues, and Henry Schreiner. +# +# Distributed under the 3-clause BSD license, see accompanying file LICENSE +# or https://github.com/scikit-hep/vector for details. + +import numpy as np +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# ROOT.Math.XYZVector constructor arguments to get all the weird cases. +constructor = [ + (0, 0, 0), + (0, 10, 0), + (0, -10, 0), + (1, 0, 0), + (1, 10, 0), + (1, -10, 0), + (1.0, 2.5, 2.0), + (1, 2.5, 2.0), + (1, -2.5, 2.0), +] + +# Coordinate conversion methods to apply to the VectorObject2D. +coordinate_list = [ + "to_xyz", + "to_rhophieta", + "to_rhophitheta", + "to_rhophiz", + "to_xyeta", + "to_xytheta", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +angle_list = [ + 0, + 0.0, + 0.7853981633974483, + -0.7853981633974483, + 1.5707963267948966, + -1.5707963267948966, + 3.141592653589793, + -3.141592653589793, + 6.283185307179586, + -6.283185307179586, +] + + +@pytest.fixture(scope="module", params=angle_list) +def angle(request): + return request.param + + +scalar_list = [ + 0, + -1, + 1.0, + 100000.0000, + -100000.0000, +] + + +@pytest.fixture(scope="module", params=scalar_list) +def scalar(request): + return request.param + + +# Run a test that compares ROOT's 'Dot()' with vector's 'dot' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Dot(constructor, coordinates): + assert ROOT.Math.XYZVector(*constructor).Dot( + ROOT.Math.XYZVector(*constructor) + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates + )().dot( + getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates + )() + ) + ) + + +# Run the same tests within hypothesis +@given( + constructor1=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), + constructor2=st.tuples( + st.floats(min_value=-10e7, max_value=10e7), + st.floats(min_value=-10e7, max_value=10e7), + ) + | st.tuples( + st.integers(min_value=-10e7, max_value=10e7), + st.integers(min_value=-10e7, max_value=10e7), + ), +) +def test_fuzz_Dot(constructor1, constructor2, coordinates): + assert ROOT.Math.XYZVector(*constructor1).Dot( + ROOT.Math.XYZVector(*constructor2) + ) == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor1))), coordinates + )().dot( + getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor2))), coordinates + )() + ) + ) + + +# Run a test that compares ROOT's 'Mag2()' with vector's 'rho2' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Mag2(constructor, coordinates): + assert ROOT.Math.XYZVector(*constructor).Mag2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates + )().rho2 + ) + + +# Run a test that compares ROOT's 'R()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_R(constructor, coordinates): + assert ROOT.Math.XYZVector(*constructor).R() == pytest.approx( + np.sqrt( + getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates + )().rho2 + ) + ) + + +# Run a test that compares ROOT's 'Phi()' with vector's 'rho' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Phi(constructor, coordinates): + assert ROOT.Math.XYZVector(*constructor).Phi() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates + )().phi + ) + + +# Run a test that compares ROOT's 'RotateX()' with vector's 'rotateX' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateX(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationX(angle) * ROOT.Math.XYZVector(*constructor) + vec = getattr(vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates)() + res_vec = vec.rotateX(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'RotateY()' with vector's 'rotateY' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateY(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationY(angle) * ROOT.Math.XYZVector(*constructor) + vec = getattr(vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates)() + res_vec = vec.rotateY(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'RotateZ()' with vector's 'rotateZ' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_RotateZ(constructor, angle, coordinates): + ref_vec = ROOT.Math.RotationZ(angle) * ROOT.Math.XYZVector(*constructor) + vec = getattr(vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates)() + res_vec = vec.rotateZ(angle) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's 'Unit()' with vector's 'unit' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_Unit(constructor, coordinates): + ref_vec = ROOT.Math.XYZVector(*constructor).Unit() + vec = getattr(vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates)() + res_vec = vec.unit + assert ref_vec.X() == pytest.approx(res_vec().x) + assert ref_vec.Y() == pytest.approx(res_vec().y) + assert ref_vec.Z() == pytest.approx(res_vec().z) + + +# Run a test that compares ROOT's 'X()' and 'Y()' with vector's 'x' and 'y' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_X_and_Y(constructor, coordinates): + vec = getattr(vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates)() + assert ROOT.Math.XYZVector(*constructor).X() == pytest.approx( + vec.x + ) and ROOT.Math.XYZVector(*constructor).Y() == pytest.approx(vec.y) + + +# Run a test that compares ROOT's '__add__' with vector's 'add' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_add(constructor, coordinates): + ref_vec = ROOT.Math.XYZVector(*constructor).__add__( + ROOT.Math.XYZVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates + )().add( + getattr(vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates)() + ) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__sub__' with vector's 'subtract' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_sub(constructor, coordinates): + ref_vec = ROOT.Math.XYZVector(*constructor).__sub__( + ROOT.Math.XYZVector(*constructor) + ) + vec1 = getattr(vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates)() + vec2 = getattr(vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates)() + res_vec = vec1.subtract(vec2) + assert ref_vec.X() == pytest.approx(res_vec.x) + assert ref_vec.Y() == pytest.approx(res_vec.y) + assert ref_vec.Z() == pytest.approx(res_vec.z) + + +# Run a test that compares ROOT's '__neg__' with vector's '__neg__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_neg(constructor, coordinates): + ref_vec = ROOT.Math.XYZVector(*constructor).__neg__() + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates + )().__neg__ + assert ref_vec.X() == pytest.approx(vec().x) + assert ref_vec.Y() == pytest.approx(vec().y) + assert ref_vec.Z() == pytest.approx(vec().z) + + +# Run a test that compares ROOT's '__mul__' with vector's 'mul' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_mul(constructor, scalar, coordinates): + ref_vec = ROOT.Math.XYZVector(*constructor).__mul__(scalar) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates + )().__mul__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__truediv__' with vector's '__truediv__' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_truediv(constructor, scalar, coordinates): + ref_vec = ROOT.Math.XYZVector(*constructor).__truediv__(scalar) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates + )().__truediv__(scalar) + assert ref_vec.X() == pytest.approx(vec.x) + assert ref_vec.Y() == pytest.approx(vec.y) + assert ref_vec.Z() == pytest.approx(vec.z) + + +# Run a test that compares ROOT's '__eq__' with vector's 'isclose' for all cases. +@pytest.mark.parametrize("constructor", constructor) +def test_eq(constructor, coordinates): + ref_vec = ROOT.Math.XYZVector(*constructor).__eq__( + ROOT.Math.XYZVector(*constructor) + ) + vec = getattr( + vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates + )().isclose( + getattr(vector.obj(**dict(zip(["x", "y", "z"], constructor))), coordinates)() + ) + assert ref_vec == vec diff --git a/tests/root/test_vector.py b/tests/root/test_vector.py new file mode 100644 index 00000000..4a14c80b --- /dev/null +++ b/tests/root/test_vector.py @@ -0,0 +1,125 @@ +# This test code was written by the `hypothesis.extra.ghostwriter` module +# and is provided under the Creative Commons Zero public domain dedication. + +import pytest +from hypothesis import given +from hypothesis import strategies as st + +import vector + +# If ROOT is not available, skip these tests. +ROOT = pytest.importorskip("ROOT") + +# Coordinate conversion methods to apply to the VectorObject4D. +coordinate_list = [ + "to_xyzt", + "to_xythetat", + "to_xyetat", + "to_rhophizt", + "to_rhophithetat", + "to_rhophietat", + "to_xyztau", + "to_xythetatau", + "to_xyetatau", + "to_rhophiztau", + "to_rhophithetatau", + "to_rhophietatau", +] + + +@pytest.fixture(scope="module", params=coordinate_list) +def coordinates(request): + return request.param + + +constructor = [ + (0, 0, 0, 0), + (0, 0, 0, 10), + (0, 0, 0, -10), + (1, 2, 3, 0), + (1, 2, 3, 10), + (1, 2, 3, -10), + (1, 2, 3, 2.5), + (1, 2, 3, -2.5), +] + + +@pytest.mark.parametrize("constructor", constructor) +def test_M2(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).M2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().tau2 + ) + + +@given( + constructor=st.tuples(st.floats(), st.floats(), st.floats(), st.floats()) + | st.tuples(st.integers(), st.integers(), st.integers(), st.integers()) +) +def test_fuzz_M2(constructor, coordinates): + assert ROOT.Math.PxPyPzEVector(*constructor).M2() == pytest.approx( + getattr( + vector.obj(**dict(zip(["x", "y", "z", "t"], constructor))), coordinates + )().tau2 + ) + + +@given( + azimuthal=st.tuples(st.floats(), st.floats()) + | st.tuples(st.integers(), st.integers()) +) +def test_fuzz_MomentumObject2D(azimuthal): + vec = vector.MomentumObject2D(azimuthal=azimuthal) + + +@given( + azimuthal=st.tuples(st.floats(), st.floats()) + | st.tuples(st.integers(), st.integers()), + longitudinal=st.floats() | st.integers(), +) +def test_fuzz_MomentumObject3D(azimuthal, longitudinal): + vec = vector.MomentumObject3D(azimuthal=azimuthal, longitudinal=longitudinal) + + +@given( + azimuthal=st.tuples(st.floats(), st.floats()) + | st.tuples(st.integers(), st.integers()), + longitudinal=st.floats() | st.integers(), + temporal=st.floats() | st.integers(), +) +def test_fuzz_MomentumObject4D(azimuthal, longitudinal, temporal): + vec = vector.MomentumObject4D( + azimuthal=azimuthal, longitudinal=longitudinal, temporal=temporal + ) + + +@given( + azimuthal=st.tuples(st.floats(), st.floats()) + | st.tuples(st.integers(), st.integers()) +) +def test_fuzz_VectorObject2D(azimuthal): + vector.VectorObject2D(azimuthal=azimuthal) + + +@given( + azimuthal=st.tuples(st.floats(), st.floats()) + | st.tuples(st.integers(), st.integers()), + longitudinal=st.floats() | st.integers(), +) +def test_fuzz_VectorObject3D(azimuthal, longitudinal): + vec = vector.VectorObject3D(azimuthal=azimuthal, longitudinal=longitudinal) + + +@given( + azimuthal=st.tuples(st.floats(), st.floats()) + | st.tuples(st.integers(), st.integers()), + longitudinal=st.floats() | st.integers(), + temporal=st.floats() | st.integers(), +) +def test_fuzz_VectorObject4D(azimuthal, longitudinal, temporal): + vec = vector.VectorObject4D( + azimuthal=azimuthal, longitudinal=longitudinal, temporal=temporal + ) + # assert (vector.obj(**dict(zip(["x", "y", "z", "t"], azimuthal[0], azimuthal[1], longitudinal, temporal)))).tau == 0 + # pytest.approx(ROOT.Math.PxPyPzEVector(azimuthal[0], azimuthal[1], longitudinal, temporal).M())