import pytest
import numpy as np
import scirs2
class TestPearsonCorrelation:
def test_pearson_perfect_positive(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([2.0, 4.0, 6.0, 8.0, 10.0])
result = scirs2.pearsonr_py(x, y)
assert "correlation" in result
assert "pvalue" in result
assert abs(result["correlation"] - 1.0) < 1e-10 assert result["pvalue"] < 0.01
def test_pearson_perfect_negative(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([10.0, 8.0, 6.0, 4.0, 2.0])
result = scirs2.pearsonr_py(x, y)
assert abs(result["correlation"] - (-1.0)) < 1e-10
assert result["pvalue"] < 0.01
def test_pearson_no_correlation(self):
np.random.seed(42)
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0])
y = np.array([5.2, 5.1, 4.9, 5.0, 5.1, 4.8, 5.2, 4.9, 5.0, 5.1])
result = scirs2.pearsonr_py(x, y)
assert abs(result["correlation"]) < 0.5
assert result["pvalue"] > 0.05
def test_pearson_moderate_correlation(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0])
y = np.array([2.1, 3.9, 6.2, 7.8, 10.1, 11.9, 14.2, 15.8, 18.1, 19.9])
result = scirs2.pearsonr_py(x, y)
assert result["correlation"] > 0.9
assert result["pvalue"] < 0.01
def test_pearson_alternative_less(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([10.0, 8.0, 6.0, 4.0, 2.0])
result = scirs2.pearsonr_py(x, y, alternative="less")
assert result["correlation"] < 0
assert "pvalue" in result
def test_pearson_alternative_greater(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([2.0, 4.0, 6.0, 8.0, 10.0])
result = scirs2.pearsonr_py(x, y, alternative="greater")
assert result["correlation"] > 0
assert result["pvalue"] < 0.05
def test_pearson_two_sided_default(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([2.0, 4.0, 6.0, 8.0, 10.0])
result_default = scirs2.pearsonr_py(x, y)
result_two_sided = scirs2.pearsonr_py(x, y, alternative="two-sided")
assert result_default["correlation"] == result_two_sided["correlation"]
assert result_default["pvalue"] == result_two_sided["pvalue"]
def test_pearson_minimum_size(self):
x = np.array([1.0, 2.0])
y = np.array([3.0, 4.0])
result = scirs2.pearsonr_py(x, y)
assert "correlation" in result
assert "pvalue" in result
class TestSpearmanCorrelation:
def test_spearman_perfect_positive(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([10.0, 20.0, 30.0, 40.0, 50.0])
result = scirs2.spearmanr_py(x, y)
assert abs(result["correlation"] - 1.0) < 1e-10
assert result["pvalue"] < 0.01
def test_spearman_perfect_negative(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([50.0, 40.0, 30.0, 20.0, 10.0])
result = scirs2.spearmanr_py(x, y)
assert abs(result["correlation"] - (-1.0)) < 1e-10
assert result["pvalue"] < 0.01
def test_spearman_nonlinear_monotonic(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
y = x ** 2
result = scirs2.spearmanr_py(x, y)
assert result["correlation"] > 0.99
assert result["pvalue"] < 0.01
def test_spearman_with_ties(self):
x = np.array([1.0, 2.0, 2.0, 3.0, 4.0])
y = np.array([5.0, 6.0, 6.0, 7.0, 8.0])
result = scirs2.spearmanr_py(x, y)
assert result["correlation"] > 0.9
assert result["pvalue"] < 0.05
def test_spearman_alternative_less(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
y = np.array([6.0, 5.0, 4.0, 3.0, 2.0, 1.0])
result = scirs2.spearmanr_py(x, y, alternative="less")
assert result["correlation"] < 0
assert "pvalue" in result
def test_spearman_alternative_greater(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
y = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
result = scirs2.spearmanr_py(x, y, alternative="greater")
assert result["correlation"] > 0
assert result["pvalue"] < 0.05
def test_spearman_no_correlation(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
y = np.array([4.0, 2.0, 6.0, 1.0, 7.0, 3.0, 8.0, 5.0])
result = scirs2.spearmanr_py(x, y)
assert abs(result["correlation"]) < 0.6
class TestKendallTauCorrelation:
def test_kendall_perfect_concordance(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([2.0, 4.0, 6.0, 8.0, 10.0])
result = scirs2.kendalltau_py(x, y)
assert abs(result["correlation"] - 1.0) < 1e-10
assert result["pvalue"] < 0.1
def test_kendall_perfect_discordance(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y = np.array([10.0, 8.0, 6.0, 4.0, 2.0])
result = scirs2.kendalltau_py(x, y)
assert abs(result["correlation"] - (-1.0)) < 1e-10
assert result["pvalue"] < 0.1
def test_kendall_method_b(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
y = np.array([1.0, 3.0, 2.0, 5.0, 4.0, 6.0])
result = scirs2.kendalltau_py(x, y, method="b")
assert result["correlation"] > 0.5
assert "pvalue" in result
def test_kendall_method_c(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
y = np.array([1.0, 3.0, 2.0, 5.0, 4.0, 6.0])
result = scirs2.kendalltau_py(x, y, method="c")
assert "correlation" in result
assert "pvalue" in result
def test_kendall_with_ties(self):
x = np.array([1.0, 2.0, 2.0, 3.0, 4.0])
y = np.array([5.0, 6.0, 6.0, 7.0, 8.0])
result = scirs2.kendalltau_py(x, y, method="b")
assert result["correlation"] > 0.7
def test_kendall_alternative_less(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
y = np.array([6.0, 5.0, 4.0, 3.0, 2.0, 1.0])
result = scirs2.kendalltau_py(x, y, method="b", alternative="less")
assert result["correlation"] < 0
assert result["pvalue"] < 0.05
def test_kendall_alternative_greater(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
y = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
result = scirs2.kendalltau_py(x, y, method="b", alternative="greater")
assert result["correlation"] > 0
assert result["pvalue"] < 0.05
def test_kendall_larger_sample(self):
np.random.seed(42)
x = np.arange(20, dtype=float)
y = x + np.random.normal(0, 2, 20)
result = scirs2.kendalltau_py(x, y)
assert result["correlation"] > 0.7
assert result["pvalue"] < 0.01
class TestCorrelationComparisons:
def test_all_methods_same_direction(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
y = np.array([2.1, 3.9, 6.1, 8.2, 9.9, 12.1, 13.8, 16.2])
pearson = scirs2.pearsonr_py(x, y)
spearman = scirs2.spearmanr_py(x, y)
kendall = scirs2.kendalltau_py(x, y)
assert pearson["correlation"] > 0
assert spearman["correlation"] > 0
assert kendall["correlation"] > 0
assert pearson["pvalue"] < 0.01
assert spearman["pvalue"] < 0.01
assert kendall["pvalue"] < 0.05
def test_spearman_vs_pearson_nonlinear(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0])
y = np.exp(x / 4.0)
pearson = scirs2.pearsonr_py(x, y)
spearman = scirs2.spearmanr_py(x, y)
assert spearman["correlation"] > pearson["correlation"]
assert abs(spearman["correlation"] - 1.0) < 0.01
def test_kendall_magnitude_smaller(self):
x = np.array([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0])
y = np.array([2.0, 3.5, 5.0, 6.5, 8.0, 9.5, 11.0, 12.5, 14.0, 15.5])
spearman = scirs2.spearmanr_py(x, y)
kendall = scirs2.kendalltau_py(x, y)
assert spearman["correlation"] > 0
assert kendall["correlation"] > 0
assert kendall["correlation"] <= spearman["correlation"] + 0.1
class TestCorrelationEdgeCases:
def test_different_lengths(self):
x = np.array([1.0, 2.0, 3.0])
y = np.array([1.0, 2.0, 3.0, 4.0])
with pytest.raises(RuntimeError):
scirs2.pearsonr_py(x, y)
with pytest.raises(RuntimeError):
scirs2.spearmanr_py(x, y)
with pytest.raises(RuntimeError):
scirs2.kendalltau_py(x, y)
def test_constant_array(self):
x = np.array([5.0, 5.0, 5.0, 5.0])
y = np.array([1.0, 2.0, 3.0, 4.0])
with pytest.raises(RuntimeError):
scirs2.pearsonr_py(x, y)
def test_invalid_alternative(self):
x = np.array([1.0, 2.0, 3.0, 4.0])
y = np.array([2.0, 4.0, 6.0, 8.0])
with pytest.raises(RuntimeError):
scirs2.pearsonr_py(x, y, alternative="invalid")
with pytest.raises(RuntimeError):
scirs2.spearmanr_py(x, y, alternative="invalid")
with pytest.raises(RuntimeError):
scirs2.kendalltau_py(x, y, alternative="invalid")
def test_invalid_kendall_method(self):
x = np.array([1.0, 2.0, 3.0, 4.0])
y = np.array([2.0, 4.0, 6.0, 8.0])
with pytest.raises(RuntimeError):
scirs2.kendalltau_py(x, y, method="invalid")
def test_small_sample_warning(self):
x = np.array([1.0, 2.0, 3.0])
y = np.array([2.0, 4.0, 6.0])
result = scirs2.pearsonr_py(x, y)
assert "correlation" in result
assert "pvalue" in result
if __name__ == "__main__":
pytest.main([__file__, "-v"])