Background
src/picmaker/enhance.py::fill_zebra_stripes runs a Python-level pixel loop over every row and every leading / trailing zero pixel:
for line in range(lines):
...
for s in range(samples):
if array2d[line, s] != 0:
break
...
for s in range(samples - 1, -1, -1):
if array2d[line, s] != 0:
break
...
For a 1024×1024 image the worst case is roughly 1024 × samples Python iterations. This is correctness-equivalent today (the existing tests/test_zebra.py tests pin the behavior) but is slow on real-mission data.
See CODEBASE_CRITIQUE.md §5 (Performance and resource use, "Finding (Medium) — enhance.fill_zebra_stripes Python-pixel loop").
Goal
Replace the inner loops with vectorized NumPy. The function fills in zero pixels at the leading and trailing edge of each row when the corresponding pixels in the rows immediately above and below are both non-zero.
Suggested approach
For each row, two booleans encode the "leading zeros prefix" and "trailing zeros suffix" extents:
is_zero = (array2d == 0)
# leading_zero[line, s] is True iff every column from 0..s on `line` is zero.
leading_zero = np.minimum.accumulate(is_zero, axis=1)
trailing_zero = np.minimum.accumulate(is_zero[:, ::-1], axis=1)[:, ::-1]
# Neighbouring-row sources for the fill.
prev_row = np.roll(array2d, 1, axis=0)
next_row = np.roll(array2d, -1, axis=0)
prev_row[0] = array2d[1] # first row uses row 1 (matches current code)
next_row[-1] = array2d[-2] # last row uses row -2
# Fill condition: pixel is in the leading/trailing zero region AND both
# neighbours have non-zero values at the same column.
fill_mask = (leading_zero | trailing_zero) & (prev_row != 0) & (next_row != 0)
filled = (prev_row.astype('int64') + next_row.astype('int64')) // 2
array2d[fill_mask] = filled[fill_mask]
The integer-division convention (the existing code uses (array_above + array_below) / 2 after int(...) casts on both operands; this produces a float but indexes assign back to the integer array) needs to be preserved bit-for-bit so the snapshot tests stay byte-identical.
Acceptance criteria
Related
CODEBASE_CRITIQUE.md §5 — original finding.
Background
src/picmaker/enhance.py::fill_zebra_stripesruns a Python-level pixel loop over every row and every leading / trailing zero pixel:For a 1024×1024 image the worst case is roughly
1024 × samplesPython iterations. This is correctness-equivalent today (the existingtests/test_zebra.pytests pin the behavior) but is slow on real-mission data.See
CODEBASE_CRITIQUE.md§5 (Performance and resource use, "Finding (Medium) —enhance.fill_zebra_stripesPython-pixel loop").Goal
Replace the inner loops with vectorized NumPy. The function fills in zero pixels at the leading and trailing edge of each row when the corresponding pixels in the rows immediately above and below are both non-zero.
Suggested approach
For each row, two booleans encode the "leading zeros prefix" and "trailing zeros suffix" extents:
The integer-division convention (the existing code uses
(array_above + array_below) / 2afterint(...)casts on both operands; this produces a float but indexes assign back to the integer array) needs to be preserved bit-for-bit so the snapshot tests stay byte-identical.Acceptance criteria
fill_zebra_stripesno longer contains a Python-levelfor line/for sloop.tests/test_zebra.pyandtests/test_pipeline_branches.py::test_zebra_pathpass unchanged.tiny_arraypattern).Related
CODEBASE_CRITIQUE.md§5 — original finding.