diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..6ddfe97 --- /dev/null +++ b/test/__init__.py @@ -0,0 +1,3 @@ +# Copyright (C) 2024 Roberto Rossini +# +# SPDX-License-Identifier: MIT diff --git a/test/helpers.py b/test/helpers.py new file mode 100644 index 0000000..332dad5 --- /dev/null +++ b/test/helpers.py @@ -0,0 +1,39 @@ +# Copyright (C) 2024 Roberto Rossini +# +# SPDX-License-Identifier: MIT + + +def numpy_avail() -> bool: + try: + import numpy + except ModuleNotFoundError: + return False + + return True + + +def pandas_avail() -> bool: + try: + import pandas + except ModuleNotFoundError: + return False + + return True + + +def pyarrow_avail() -> bool: + try: + import pyarrow + except ModuleNotFoundError: + return False + + return True + + +def scipy_avail() -> bool: + try: + import scipy + except ModuleNotFoundError: + return False + + return True diff --git a/test/test_fetch_dense.py b/test/test_fetch_dense.py index fe88b26..55f3fff 100644 --- a/test/test_fetch_dense.py +++ b/test/test_fetch_dense.py @@ -4,12 +4,12 @@ import pathlib -import numpy as np -import numpy.typing as npt import pytest import hictkpy +from .helpers import numpy_avail + testdir = pathlib.Path(__file__).resolve().parent pytestmark = pytest.mark.parametrize( @@ -21,7 +21,9 @@ ) -def issymmetric(m: npt.NDArray) -> bool: +def issymmetric(m) -> bool: + import numpy as np + assert m.ndim == 2 if m.size == 0: return True @@ -31,6 +33,7 @@ def issymmetric(m: npt.NDArray) -> bool: return np.allclose(m, m.T, atol=0.0, rtol=0.0) +@pytest.mark.skipif(not numpy_avail(), reason="numpy is not available") class TestClass: def test_genome_wide(self, file, resolution): f = hictkpy.File(file, resolution) @@ -40,6 +43,8 @@ def test_genome_wide(self, file, resolution): assert issymmetric(m) def test_cis(self, file, resolution): + import numpy as np + f = hictkpy.File(file, resolution) m = f.fetch("chr2R:10,000,000-15,000,000").to_numpy() assert m.shape == (50, 50) @@ -68,6 +73,8 @@ def test_cis(self, file, resolution): assert m.sum() == 12_607_205 def test_trans(self, file, resolution): + import numpy as np + f = hictkpy.File(file, resolution) m = f.fetch("chr2R:10,000,000-15,000,000", "chrX:0-10,000,000").to_numpy() assert m.shape == (50, 100) diff --git a/test/test_fetch_df.py b/test/test_fetch_df.py index 015fc3d..da6563c 100644 --- a/test/test_fetch_df.py +++ b/test/test_fetch_df.py @@ -2,13 +2,15 @@ # # SPDX-License-Identifier: MIT +import math import pathlib -import numpy as np import pytest import hictkpy +from .helpers import numpy_avail, pandas_avail, pyarrow_avail + testdir = pathlib.Path(__file__).resolve().parent pytestmark = pytest.mark.parametrize( @@ -20,16 +22,7 @@ ) -def pandas_avail() -> bool: - try: - import pandas - except ModuleNotFoundError: - return False - - return True - - -@pytest.mark.skipif(not pandas_avail(), reason="pandas is not available") +@pytest.mark.skipif(not pandas_avail() or not pyarrow_avail(), reason="either pandas or pyarrow are not available") class TestClass: def test_genome_wide(self, file, resolution): f = hictkpy.File(file, resolution) @@ -54,11 +47,14 @@ def test_cis(self, file, resolution): assert df["chrom1"].dtype.name == "category" assert df["chrom2"].dtype.name == "category" - df = f.fetch("chr2R:10,000,000-15,000,000", count_type="int").to_df() - assert df["count"].dtype == np.int32 + if numpy_avail(): + import numpy as np + + df = f.fetch("chr2R:10,000,000-15,000,000", count_type="int").to_df() + assert df["count"].dtype == np.int32 - df = f.fetch("chr2R:10,000,000-15,000,000", count_type="float").to_df() - assert df["count"].dtype == np.float64 + df = f.fetch("chr2R:10,000,000-15,000,000", count_type="float").to_df() + assert df["count"].dtype == np.float64 df = f.fetch("chr2R\t10000000\t15000000", query_type="BED").to_df() assert len(df) == 1275 @@ -87,11 +83,14 @@ def test_trans(self, file, resolution): assert df["chrom1"].dtype.name == "category" assert df["chrom2"].dtype.name == "category" - df = f.fetch("chr2R:10,000,000-15,000,000", "chrX:0-10,000,000", count_type="int").to_df() - assert df["count"].dtype == np.int32 + if numpy_avail(): + import numpy as np + + df = f.fetch("chr2R:10,000,000-15,000,000", "chrX:0-10,000,000", count_type="int").to_df() + assert df["count"].dtype == np.int32 - df = f.fetch("chr2R:10,000,000-15,000,000", "chrX:0-10,000,000", count_type="float").to_df() - assert df["count"].dtype == np.float64 + df = f.fetch("chr2R:10,000,000-15,000,000", "chrX:0-10,000,000", count_type="float").to_df() + assert df["count"].dtype == np.float64 df = f.fetch("chr2R\t10000000\t15000000", "chrX\t0\t10000000", query_type="BED").to_df() assert len(df) == 4995 @@ -112,4 +111,4 @@ def test_balanced(self, file, resolution): else: df = f.fetch("chr2R:10,000,000-15,000,000", normalization="ICE").to_df() - assert np.isclose(59.349524704033215, df["count"].sum()) + assert math.isclose(59.349524704033215, df["count"].sum(), rel_tol=1.0e-5, abs_tol=1.0e-8) diff --git a/test/test_fetch_iters.py b/test/test_fetch_iters.py index e3cb757..3680ff0 100644 --- a/test/test_fetch_iters.py +++ b/test/test_fetch_iters.py @@ -2,9 +2,9 @@ # # SPDX-License-Identifier: MIT +import math import pathlib -import numpy as np import pytest import hictkpy @@ -87,4 +87,4 @@ def test_balanced(self, file, resolution): else: sel = f.fetch("chr2R:10,000,000-15,000,000", normalization="ICE") - assert np.isclose(59.349524704033215, compute_sum(sel)) + assert math.isclose(59.349524704033215, compute_sum(sel), rel_tol=1.0e-5, abs_tol=1.0e-8) diff --git a/test/test_fetch_sparse.py b/test/test_fetch_sparse.py index 919ead0..a9f7b4f 100644 --- a/test/test_fetch_sparse.py +++ b/test/test_fetch_sparse.py @@ -2,13 +2,15 @@ # # SPDX-License-Identifier: MIT +import math import pathlib -import numpy as np import pytest import hictkpy +from .helpers import numpy_avail, scipy_avail + testdir = pathlib.Path(__file__).resolve().parent pytestmark = pytest.mark.parametrize( @@ -20,15 +22,6 @@ ) -def scipy_avail() -> bool: - try: - import scipy - except ModuleNotFoundError: - return False - - return True - - @pytest.mark.skipif(not scipy_avail(), reason="scipy is not available") class TestClass: def test_genome_wide(self, file, resolution): @@ -45,11 +38,14 @@ def test_cis(self, file, resolution): assert m.shape == (50, 50) assert m.sum() == 4_519_080 - m = f.fetch("chr2R:10,000,000-15,000,000", count_type="int").to_coo() - assert m.dtype == np.int32 + if numpy_avail(): + import numpy as np + + m = f.fetch("chr2R:10,000,000-15,000,000", count_type="int").to_coo() + assert m.dtype == np.int32 - m = f.fetch("chr2R:10,000,000-15,000,000", count_type="float").to_coo() - assert m.dtype == np.float64 + m = f.fetch("chr2R:10,000,000-15,000,000", count_type="float").to_coo() + assert m.dtype == np.float64 m = f.fetch("chr2R\t10000000\t15000000", query_type="BED").to_coo() assert m.shape == (50, 50) @@ -69,11 +65,14 @@ def test_trans(self, file, resolution): assert m.shape == (50, 100) assert m.sum() == 83_604 - m = f.fetch("chr2R:10,000,000-15,000,000", "chrX:0-10,000,000", count_type="int").to_coo() - assert m.dtype == np.int32 + if numpy_avail(): + import numpy as np + + m = f.fetch("chr2R:10,000,000-15,000,000", "chrX:0-10,000,000", count_type="int").to_coo() + assert m.dtype == np.int32 - m = f.fetch("chr2R:10,000,000-15,000,000", "chrX:0-10,000,000", count_type="float").to_coo() - assert m.dtype == np.float64 + m = f.fetch("chr2R:10,000,000-15,000,000", "chrX:0-10,000,000", count_type="float").to_coo() + assert m.dtype == np.float64 m = f.fetch("chr2R\t10000000\t15000000", "chrX\t0\t10000000", query_type="BED").to_coo() assert m.shape == (50, 100) @@ -86,4 +85,4 @@ def test_balanced(self, file, resolution): else: m = f.fetch("chr2R:10,000,000-15,000,000", normalization="ICE").to_coo() - assert np.isclose(59.349524704033215, m.sum()) + assert math.isclose(59.349524704033215, m.sum(), rel_tol=1.0e-5, abs_tol=1.0e-8) diff --git a/test/test_file_creation_cool.py b/test/test_file_creation_cool.py index 1120f4c..06af872 100644 --- a/test/test_file_creation_cool.py +++ b/test/test_file_creation_cool.py @@ -30,7 +30,16 @@ def pandas_avail() -> bool: return True -@pytest.mark.skipif(not pandas_avail(), reason="pandas is not available") +def pyarrow_avail() -> bool: + try: + import pyarrow + except ModuleNotFoundError: + return False + + return True + + +@pytest.mark.skipif(not pandas_avail() or not pyarrow_avail(), reason="either pandas or pyarrow are not available") class TestClass: @staticmethod def setup_method(): diff --git a/test/test_file_creation_hic.py b/test/test_file_creation_hic.py index 1ebdff1..c4fa3a4 100644 --- a/test/test_file_creation_hic.py +++ b/test/test_file_creation_hic.py @@ -30,7 +30,16 @@ def pandas_avail() -> bool: return True -@pytest.mark.skipif(not pandas_avail(), reason="pandas is not available") +def pyarrow_avail() -> bool: + try: + import pyarrow + except ModuleNotFoundError: + return False + + return True + + +@pytest.mark.skipif(not pandas_avail() or not pyarrow_avail(), reason="either pandas or pyarrow are not available") class TestClass: @staticmethod def setup_method():