Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions pywt/_dwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ def pad(x, pad_widths, mode):
pad_widths = np.array(pad_widths)
pad_widths = np.round(pad_widths).astype(np.intp, copy=False)
if pad_widths.min() < 0:
raise ValueError("pad_widths must be > 0")
raise ValueError("pad_widths must be >= 0")
pad_widths = np.broadcast_to(pad_widths, (x.ndim, 2)).tolist()

if mode in ['symmetric', 'reflect']:
Expand All @@ -468,9 +468,12 @@ def pad_smooth(vector, pad_width, iaxis, kwargs):
left + np.arange(pad_width[0], 0, -1) * slope_left

# smooth extension to right
right = vector[-pad_width[1] - 1]
slope_right = (right - vector[-pad_width[1] - 2])
vector[-pad_width[1]:] = \
# Note: indices are measured from the start of the vector so that
# a pad width of 0 gives an empty slice rather than the full one.
iright = vector.size - pad_width[1] - 1
right = vector[iright]
slope_right = (right - vector[iright - 1])
vector[iright + 1:] = \
right + np.arange(1, pad_width[1] + 1) * slope_right
return vector
xp = np.pad(x, pad_widths, pad_smooth)
Expand All @@ -481,7 +484,7 @@ def pad_antisymmetric(vector, pad_width, iaxis, kwargs):
npad_l, npad_r = pad_width
vsize_nonpad = vector.size - npad_l - npad_r
# Note: must modify vector in-place
vector[:] = np.pad(vector[pad_width[0]:-pad_width[-1]],
vector[:] = np.pad(vector[npad_l:vector.size - npad_r],
pad_width, mode='symmetric')
vp = vector
r_edge = npad_l + vsize_nonpad - 1
Expand Down
31 changes: 31 additions & 0 deletions pywt/tests/test_dwt_idwt.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,37 @@ def test_pad_1d():
pywt.pad(x, (4, 4), 'periodic'))


def test_pad_zero_width():
# zero pad width is a no-op for all modes except 'periodization', which
# also promotes odd-length axes to even length (gh-589)
for ndim in [1, 2, 3]:
x = np.arange(3.0**ndim).reshape((3, ) * ndim)
for mode in pywt.Modes.modes:
if mode == 'periodization':
continue
assert_array_equal(pywt.pad(x, 0, mode), x,
err_msg=f"mode={mode}, ndim={ndim}")


def test_pad_one_sided():
# a zero pad width on only one side of the axis (gh-589)
x = [1, 2, 3]
assert_array_equal(pywt.pad(x, (2, 0), 'smooth'), [-1, 0, 1, 2, 3])
assert_array_equal(pywt.pad(x, (0, 2), 'smooth'), [1, 2, 3, 4, 5])
assert_array_equal(pywt.pad(x, (2, 0), 'antisymmetric'), [-2, -1, 1, 2, 3])
assert_array_equal(pywt.pad(x, (0, 2), 'antisymmetric'), [1, 2, 3, -3, -2])

# one-sided padding matches the corresponding slice of two-sided padding
for mode in pywt.Modes.modes:
if mode == 'periodization':
continue
two_sided = pywt.pad(x, (4, 6), mode)
assert_array_equal(pywt.pad(x, (4, 0), mode), two_sided[:-6],
err_msg=f"mode={mode}")
assert_array_equal(pywt.pad(x, (0, 6), mode), two_sided[4:],
err_msg=f"mode={mode}")


def test_pad_errors():
# negative pad width
x = [1, 2, 3]
Expand Down