Test Cases¶
The test_2_case() tests in Local Usage and Nonlocal Usage
showcase the fact that the brute force case and the MiLoMerge package produce the same
result. Selected tests are shown below, but one can also
look at the source code on Git
if desired.
Local Usage¶
import numpy as np
import pytest
import MiLoMerge
import helpers
def test_naive():
h1 = np.zeros(30)
h1[0] = 5
h1[1] = 1
h2 = np.zeros(30)
h2[2] = 5
h2[3] = 2
h3 = np.zeros(30)
h3[4] = 5
h3[5] = 3
merger = MiLoMerge.MergerLocal(
range(31), #bin edges
h1,
h2,
h3
)
new_edges, new_counts = merger.run(3, return_counts=True)
assert np.count_nonzero(new_counts[0] == 6) == 1
assert np.count_nonzero(new_counts[0] == 0) == 2
assert np.all(new_counts[0][new_counts[1] == 7] == 0)
assert np.all(new_counts[0][new_counts[2] == 8] == 0)
assert np.count_nonzero(new_counts[1] == 7) == 1
assert np.count_nonzero(new_counts[1] == 0) == 2
assert np.all(new_counts[1][new_counts[0] == 6] == 0)
assert np.all(new_counts[1][new_counts[2] == 8] == 0)
assert np.count_nonzero(new_counts[2] == 8) == 1
assert np.count_nonzero(new_counts[2] == 0) == 2
assert np.all(new_counts[2][new_counts[0] == 6] == 0)
assert np.all(new_counts[2][new_counts[1] == 7] == 0)
assert np.array_equal(new_edges, [0,2,4,30])
def test_naive_comp_first():
h1 = np.zeros(30)
h1[0] = 5
h1[1] = 1
h2 = np.zeros(30)
h2[2] = 5
h2[3] = 2
h3 = np.zeros(30)
h3[4] = 5
h3[5] = 3
merger = MiLoMerge.MergerLocal(
range(31), #bin edges
h1,
h2,
h3,
comp_to_first=True
)
new_edges, new_counts = merger.run(2, return_counts=True)
nonzero_h1_mask = new_counts[0] == 6
zero_h1_mask = new_counts[0] == 0
assert new_counts[1][nonzero_h1_mask] == 0
assert new_counts[1][zero_h1_mask] == 7
assert new_counts[2][nonzero_h1_mask] == 0
assert new_counts[2][zero_h1_mask] == 8
assert np.array_equal(new_edges, [0,2,30])
def test_2_case():
h1 = np.array([3,4,5,6,8,9,10], dtype=np.float64)
h2 = np.array([5,4,3,8,21,9,2], dtype=np.float64)
assert len(h1) == len(h2)
merger = MiLoMerge.MergerLocal(
range(len(h1) + 1), #bin edges
h1,
h2
)
_, (h1_MLM, h2_MLM) = merger.run(2, return_counts=True)
h1_BF, h2_BF = helpers.brute_force(h1, h2, 2, local=True)
assert np.array_equal(h1_BF.sort(), h1_MLM.sort())
assert np.array_equal(h2_BF.sort(), h2_MLM.sort())
def test_invalid_binsize_1d():
h1 = [1,2,3]
h2 = [4,5,6]
with pytest.raises(ValueError) as exc_info:
MiLoMerge.MergerLocal(
range(3),
h1,
h2
)
assert "len(counts) =" in str(exc_info.value)
assert exc_info.type is ValueError
# if __name__ == "__main__":
# test_2_case()
Nonlocal Usage¶
import numpy as np
import pytest
import MiLoMerge
import helpers
def test_naive():
h1 = np.zeros(30)
h1[0] = 5
h1[3] = 1
h2 = np.zeros(30)
h2[1] = 5
h2[4] = 2
h3 = np.zeros(30)
h3[2] = 5
h3[5] = 3
merger = MiLoMerge.MergerNonlocal(
range(31), #bin edges
h1,
h2,
h3
)
new_counts = merger.run(3)
assert np.count_nonzero(new_counts[0] == 6) == 1
assert np.count_nonzero(new_counts[0] == 0) == 2
assert np.all(new_counts[0][new_counts[1] == 7] == 0)
assert np.all(new_counts[0][new_counts[2] == 8] == 0)
assert np.count_nonzero(new_counts[1] == 7) == 1
assert np.count_nonzero(new_counts[1] == 0) == 2
assert np.all(new_counts[1][new_counts[0] == 6] == 0)
assert np.all(new_counts[1][new_counts[2] == 8] == 0)
assert np.count_nonzero(new_counts[2] == 8) == 1
assert np.count_nonzero(new_counts[2] == 0) == 2
assert np.all(new_counts[2][new_counts[0] == 6] == 0)
assert np.all(new_counts[2][new_counts[1] == 7] == 0)
def test_naive_comp_first():
h1 = np.zeros(30)
h1[0] = 5
h1[3] = 1
h2 = np.zeros(30)
h2[1] = 5
h2[4] = 2
h3 = np.zeros(30)
h3[2] = 5
h3[5] = 3
merger = MiLoMerge.MergerNonlocal(
range(31), #bin edges
h1,
h2,
h3,
comp_to_first=True
)
new_counts = merger.run(2)
nonzero_h1_mask = new_counts[0] == 6
zero_h1_mask = new_counts[0] == 0
assert new_counts[1][nonzero_h1_mask] == 0
assert new_counts[1][zero_h1_mask] == 7
assert new_counts[2][nonzero_h1_mask] == 0
assert new_counts[2][zero_h1_mask] == 8
def test_2_case():
h1 = np.array([3,4,5,6,8,9,10], dtype=np.float64)
h2 = np.array([5,4,3,8,21,9,2], dtype=np.float64)
assert len(h1) == len(h2)
h1_BF, h2_BF = helpers.brute_force(h1, h2, 2)
merger = MiLoMerge.MergerNonlocal(
range(len(h1) + 1), #bin edges
h1,
h2
)
h1_MLM, h2_MLM = merger.run(2)
assert np.array_equal(h1_BF.sort(), h1_MLM.sort())
assert np.array_equal(h2_BF.sort(), h2_MLM.sort())
def test_invalid_binsize_1d():
h1 = [1,2,3]
h2 = [4,5,6]
with pytest.raises(ValueError) as exc_info:
MiLoMerge.MergerNonlocal(
range(3),
h1,
h2
)
assert "Bin edges are of invalid size" in str(exc_info.value)
assert exc_info.type is ValueError
def test_invalid_binsize_2d():
h1 = np.array([
[1,2,3],
[4,5,6]
])
h2 = np.array([
[7,8,9],
[10,11,12]
])
with pytest.raises(ValueError) as exc_info:
MiLoMerge.MergerNonlocal(
(range(3), range(3)),
h1,
h2
)
assert "Bin edge for dimension 1" in str(exc_info.value)
assert exc_info.type is ValueError
def test_invalid_number_of_bins():
h1 = np.array([
[1,2,3],
[4,5,6]
])
h2 = np.array([
[7,8,9],
[10,11,12]
])
with pytest.raises(IndexError) as exc_info:
MiLoMerge.MergerNonlocal(
(range(3),),
h1,
h2
)
assert "No bin edges provided" in str(exc_info.value)
assert exc_info.type is IndexError
Post-merging Bin Placement¶
import numpy as np
import pytest
import MiLoMerge
import helpers
def test_local_placement():
bin_centers = (np.arange(1, 31) + np.arange(30))/2
h1 = np.zeros(30)
h1[0] = 5
h1[1] = 1
h1_data = [bin_centers[0]]*int(h1[0]) + [bin_centers[1]]*int(h1[1])
h2 = np.zeros(30)
h2[2] = 5
h2[3] = 2
h2_data = [bin_centers[2]]*int(h2[2]) + [bin_centers[3]]*int(h2[3])
h3 = np.zeros(30)
h3[4] = 5
h3[5] = 3
h3_data = [bin_centers[4]]*int(h3[4]) + [bin_centers[5]]*int(h3[5])
merger = MiLoMerge.MergerLocal(
range(31), #bin edges
h1,
h2,
h3,
map_at=(3,)
)
new_edges, new_counts = merger.run(3, return_counts=True)
for i, arr in enumerate((h1_data, h2_data, h3_data)):
c, b = MiLoMerge.place_local(3, arr, "./", verbose=False)
assert np.array_equal(c, new_counts[i])
assert np.array_equal(b, new_edges)
def test_nonlocal_placement_1d():
bin_centers = (np.arange(1, 31) + np.arange(30))/2
h1 = np.zeros(30)
h1[0] = 5
h1[3] = 1
h1_data = [bin_centers[0]]*int(h1[0]) + [bin_centers[3]]*int(h1[3])
h2 = np.zeros(30)
h2[1] = 5
h2[4] = 2
h2_data = [bin_centers[1]]*int(h2[1]) + [bin_centers[4]]*int(h2[4])
h3 = np.zeros(30)
h3[2] = 5
h3[5] = 3
h3_data = [bin_centers[2]]*int(h3[2]) + [bin_centers[5]]*int(h3[5])
merger = MiLoMerge.MergerNonlocal(
range(31), #bin edges
h1,
h2,
h3,
map_at=(3,)
)
new_counts = merger.run(3)
for i, arr in enumerate((h1_data, h2_data, h3_data)):
temp_counts = np.zeros(3)
placements = MiLoMerge.place_array_nonlocal(3, arr, "./")
temp_counts, _ = np.histogram(placements, range(3+1))
assert np.array_equal(temp_counts, new_counts[i])