import numpy as np from challenge_tools.metrics import spectrogram, spectrogram_l2, waveform_l2 from challenge_tools.reference import OrderInfo, collect_order, maximal_elements, select_reference def test_waveform_l2(): r = np.array([1.0, 2.0, 2.0]) assert waveform_l2(r, r) == 0.0 assert abs(waveform_l2(r * 1.1, r) - 0.1) < 1e-12 def test_spectrogram_shape(): x = np.zeros(96000) s = spectrogram(x, 2048, 512) assert s.shape == ((96000 - 2048) // 512 + 1, 1025) def test_spectrogram_phase_insensitive(): t = np.arange(96000) / 48000 a = np.sin(2 * np.pi * 440 * t) b = np.sin(2 * np.pi * 440 * t + 1.0) assert waveform_l2(a, b) > 0.5 assert spectrogram_l2(a, b, 2048, 512) < 1e-2 def test_reference_selection_prefers_order_preserving_candidate(): subs = [ {"submission_id": "x", "solutions": [ {"solution_id": "a", "more_accurate_than": []}, {"solution_id": "b", "more_accurate_than": ["a"]}, ]}, {"submission_id": "y", "solutions": [ {"solution_id": "c", "more_accurate_than": []}, {"solution_id": "d", "more_accurate_than": ["c"]}, ]}, ] info = collect_order(subs) assert set(maximal_elements(info)) == {"x/b", "y/d"} # Truth: x/b is exact; y/d is wrong. Errors to x/b respect y's chain, errors to y/d do not respect x's chain. keys = ["x/a", "x/b", "y/c", "y/d"] truth = {"x/a": 1.0, "x/b": 0.0, "y/c": 3.0, "y/d": 2.5} err = {a: {b: abs(truth[a] - truth[b]) for b in keys} for a in keys} # under y/d: err(x/b)=2.5 > err(x/a)=1.5, so x's pair is violated rep = select_reference(info, err) assert rep["reference"] == "x/b" assert rep["candidates"][0]["score"] == 1.0 def test_reference_selection_medoid_fallback(): info = OrderInfo(pairs=[], submission_of={"p/a": "p", "q/b": "q", "r/c": "r"}) keys = list(info.submission_of) pos = {"p/a": 0.0, "q/b": 1.0, "r/c": 5.0} err = {a: {b: abs(pos[a] - pos[b]) for b in keys} for a in keys} rep = select_reference(info, err) assert rep["reference"] == "q/b"