From cf59f6c2dad8acb8c4f6d18f6089b0faa2added8 Mon Sep 17 00:00:00 2001 From: Miki Watanabe <105326591+MikiPWata@users.noreply.github.com> Date: Wed, 16 Nov 2022 10:08:18 +0900 Subject: DOC: Update parameter descriptions for np.pad (#22519) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some parameters like pad_width or stat_length claimed to expect tuples-of-tuples as input, but in practice they also work with single tuples. The parameter descriptions of the relevant parameters are updated in the docstring to reflect this implicit tuple wrapping behavior. Co-authored-by: 渡邉 美希 --- numpy/lib/arraypad.py | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'numpy/lib/arraypad.py') diff --git a/numpy/lib/arraypad.py b/numpy/lib/arraypad.py index 8830b8147..28123246d 100644 --- a/numpy/lib/arraypad.py +++ b/numpy/lib/arraypad.py @@ -537,11 +537,12 @@ def pad(array, pad_width, mode='constant', **kwargs): The array to pad. pad_width : {sequence, array_like, int} Number of values padded to the edges of each axis. - ((before_1, after_1), ... (before_N, after_N)) unique pad widths + ``((before_1, after_1), ... (before_N, after_N))`` unique pad widths for each axis. - ((before, after),) yields same before and after pad for each axis. - (pad,) or int is a shortcut for before = after = pad width for all - axes. + ``(before, after)`` or ``((before, after),)`` yields same before + and after pad for each axis. + ``(pad,)`` or ``int`` is a shortcut for before = after = pad width + for all axes. mode : str or function, optional One of the following string values or a user supplied function. @@ -586,14 +587,14 @@ def pad(array, pad_width, mode='constant', **kwargs): Used in 'maximum', 'mean', 'median', and 'minimum'. Number of values at edge of each axis used to calculate the statistic value. - ((before_1, after_1), ... (before_N, after_N)) unique statistic + ``((before_1, after_1), ... (before_N, after_N))`` unique statistic lengths for each axis. - ((before, after),) yields same before and after statistic lengths - for each axis. + ``(before, after)`` or ``((before, after),)`` yields same before + and after statistic lengths for each axis. - (stat_length,) or int is a shortcut for before = after = statistic - length for all axes. + ``(stat_length,)`` or ``int`` is a shortcut for + ``before = after = statistic`` length for all axes. Default is ``None``, to use the entire axis. constant_values : sequence or scalar, optional @@ -603,11 +604,11 @@ def pad(array, pad_width, mode='constant', **kwargs): ``((before_1, after_1), ... (before_N, after_N))`` unique pad constants for each axis. - ``((before, after),)`` yields same before and after constants for each - axis. + ``(before, after)`` or ``((before, after),)`` yields same before + and after constants for each axis. - ``(constant,)`` or ``constant`` is a shortcut for ``before = after = constant`` for - all axes. + ``(constant,)`` or ``constant`` is a shortcut for + ``before = after = constant`` for all axes. Default is 0. end_values : sequence or scalar, optional @@ -617,11 +618,11 @@ def pad(array, pad_width, mode='constant', **kwargs): ``((before_1, after_1), ... (before_N, after_N))`` unique end values for each axis. - ``((before, after),)`` yields same before and after end values for each - axis. + ``(before, after)`` or ``((before, after),)`` yields same before + and after end values for each axis. - ``(constant,)`` or ``constant`` is a shortcut for ``before = after = constant`` for - all axes. + ``(constant,)`` or ``constant`` is a shortcut for + ``before = after = constant`` for all axes. Default is 0. reflect_type : {'even', 'odd'}, optional -- cgit v1.2.1 From 2aad439eec34a80aaac0fd61a9b8de809710efa5 Mon Sep 17 00:00:00 2001 From: LU <32014765+LuYunChi@users.noreply.github.com> Date: Wed, 7 Dec 2022 09:29:31 -0500 Subject: BUG: fix unexpected return of np.pad with mode=wrap (#22575) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit np.pad with mode="wrap" returns unexpected result that original data is not strictly looped in padding. This may happen in some occassions when padding widths in the same dimension are unbalanced (see added testcase in test_arraypad.py and the related issue). The reason is the function pad makes iterative calls of _set_wrap_both() in the above situation, yet period for padding is not correctly computed in each iteration. The bug is fixed by guaranteeing that period is always a multiple of original data size, and also be the possible maximum for computation efficiency. Closes #22464 Co-authored-by: Lars Grüter --- numpy/lib/arraypad.py | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'numpy/lib/arraypad.py') diff --git a/numpy/lib/arraypad.py b/numpy/lib/arraypad.py index 28123246d..b06a645d8 100644 --- a/numpy/lib/arraypad.py +++ b/numpy/lib/arraypad.py @@ -378,7 +378,7 @@ def _set_reflect_both(padded, axis, width_pair, method, include_edge=False): return left_pad, right_pad -def _set_wrap_both(padded, axis, width_pair): +def _set_wrap_both(padded, axis, width_pair, original_period): """ Pad `axis` of `arr` with wrapped values. @@ -391,6 +391,8 @@ def _set_wrap_both(padded, axis, width_pair): width_pair : (int, int) Pair of widths that mark the pad area on both sides in the given dimension. + original_period : int + Original length of data on `axis` of `arr`. Returns ------- @@ -400,6 +402,9 @@ def _set_wrap_both(padded, axis, width_pair): """ left_pad, right_pad = width_pair period = padded.shape[axis] - right_pad - left_pad + # Avoid wrapping with only a subset of the original area by ensuring period + # can only be a multiple of the original area's length. + period = period // original_period * original_period # If the current dimension of `arr` doesn't contain enough valid values # (not part of the undefined pad area) we need to pad multiple times. @@ -410,14 +415,12 @@ def _set_wrap_both(padded, axis, width_pair): if left_pad > 0: # Pad with wrapped values on left side - # First slice chunk from right side of the non-pad area. + # First slice chunk from left side of the non-pad area. # Use min(period, left_pad) to ensure that chunk is not larger than - # pad area - right_slice = _slice_at_axis( - slice(-right_pad - min(period, left_pad), - -right_pad if right_pad != 0 else None), - axis - ) + # pad area. + slice_end = left_pad + period + slice_start = slice_end - min(period, left_pad) + right_slice = _slice_at_axis(slice(slice_start, slice_end), axis) right_chunk = padded[right_slice] if left_pad > period: @@ -431,11 +434,12 @@ def _set_wrap_both(padded, axis, width_pair): if right_pad > 0: # Pad with wrapped values on right side - # First slice chunk from left side of the non-pad area. + # First slice chunk from right side of the non-pad area. # Use min(period, right_pad) to ensure that chunk is not larger than - # pad area - left_slice = _slice_at_axis( - slice(left_pad, left_pad + min(period, right_pad),), axis) + # pad area. + slice_start = -right_pad - period + slice_end = slice_start + min(period, right_pad) + left_slice = _slice_at_axis(slice(slice_start, slice_end), axis) left_chunk = padded[left_slice] if right_pad > period: @@ -867,11 +871,12 @@ def pad(array, pad_width, mode='constant', **kwargs): elif mode == "wrap": for axis, (left_index, right_index) in zip(axes, pad_width): roi = _view_roi(padded, original_area_slice, axis) + original_period = padded.shape[axis] - right_index - left_index while left_index > 0 or right_index > 0: # Iteratively pad until dimension is filled with wrapped # values. This is necessary if the pad area is larger than # the length of the original values in the current dimension. left_index, right_index = _set_wrap_both( - roi, axis, (left_index, right_index)) + roi, axis, (left_index, right_index), original_period) return padded -- cgit v1.2.1