diff --git a/dpti/lib/utils.py b/dpti/lib/utils.py index 354e426..914e8b4 100644 --- a/dpti/lib/utils.py +++ b/dpti/lib/utils.py @@ -206,14 +206,20 @@ def copy_file_list(file_list, from_path, to_path): def block_avg(inp, skip=0, block_size=10): + """Return a block average and error from complete post-skip blocks.""" + if block_size <= 0: + raise ValueError("block_size must be a positive integer") inp = inp[skip:] + if len(inp) < block_size: + raise ValueError( + "block_avg requires at least one complete block after skip: " + f"got {len(inp)} samples for block_size={block_size}" + ) + nblocks = len(inp) // block_size data_chunks = [ - list(inp[i : i + block_size]) for i in range(0, len(inp), block_size) + list(inp[i : i + block_size]) + for i in range(0, nblocks * block_size, block_size) ] - nblocks = len(data_chunks) - if len(data_chunks[-1]) != block_size: - nblocks -= 1 - data_chunks = data_chunks[:nblocks] assert len(data_chunks) == nblocks # naive avg naive_avg = np.average(inp) diff --git a/tests/test_lib_utils.py b/tests/test_lib_utils.py index f801ff6..502eb4c 100644 --- a/tests/test_lib_utils.py +++ b/tests/test_lib_utils.py @@ -116,6 +116,14 @@ def test_normal(self): self.assertAlmostEqual(avg1, avg2, places=8) self.assertAlmostEqual(err1, err2, places=8) + def test_rejects_partial_only_input(self): + with self.assertRaisesRegex(ValueError, "at least one complete block"): + block_avg(np.arange(5), block_size=10) + + def test_rejects_empty_post_skip_input(self): + with self.assertRaisesRegex(ValueError, "got 0 samples"): + block_avg(np.arange(5), skip=5, block_size=2) + class TestIntegrateRangeHti(unittest.TestCase): def setUp(self):