def pad_reuse(array, pad_width, mode, **kwargs): """ Helper function for padding boundaries with values in the array. Handles the cases where the padding is constructed from values in the array. Namely by reflecting them or tiling them to create periodic boundary constraints. """ if mode in {"reflect", "symmetric"}: reflect_type = kwargs.get("reflect", "even") if reflect_type == "odd": raise NotImplementedError( "`pad` does not support `reflect_type` of `odd`.") if reflect_type != "even": raise ValueError( "unsupported value for reflect_type, must be one of (`even`, `odd`)" ) result = np.empty(array.ndim * (3, ), dtype=object) for idx in np.ndindex(result.shape): select = [] orient = [] for i, s, pw in zip(idx, array.shape, pad_width): if mode == "wrap": pw = pw[::-1] if i < 1: if mode == "reflect": select.append(slice(1, pw[0] + 1, None)) else: select.append(slice(None, pw[0], None)) elif i > 1: if mode == "reflect": select.append(slice(s - pw[1] - 1, s - 1, None)) else: select.append(slice(s - pw[1], None, None)) else: select.append(slice(None)) if i != 1 and mode in ["reflect", "symmetric"]: orient.append(slice(None, None, -1)) else: orient.append(slice(None)) select = tuple(select) orient = tuple(orient) if mode == "wrap": idx = tuple(2 - i for i in idx) result[idx] = array[select][orient] result = block(result.tolist()) return result
def tile(A, reps): try: tup = tuple(reps) except TypeError: tup = (reps, ) if any(i < 0 for i in tup): raise ValueError("Negative `reps` are not allowed.") c = asarray(A) if all(tup): for nrep in tup[::-1]: c = nrep * [c] return block(c) d = len(tup) if d < c.ndim: tup = (1, ) * (c.ndim - d) + tup if c.ndim < d: shape = (1, ) * (d - c.ndim) + c.shape else: shape = c.shape shape_out = tuple(s * t for s, t in zip(shape, tup)) return empty(shape=shape_out, dtype=c.dtype)
def pad_stats(array, pad_width, mode, stat_length): """ Helper function for padding boundaries with statistics from the array. In cases where the padding requires computations of statistics from part or all of the array, this function helps compute those statistics as requested and then adds those statistics onto the boundaries of the array. """ if mode == "median": raise NotImplementedError("`pad` does not support `mode` of `median`.") stat_length = expand_pad_value(array, stat_length) result = np.empty(array.ndim * (3, ), dtype=object) for idx in np.ndindex(result.shape): axes = [] select = [] pad_shape = [] pad_chunks = [] for d, (i, s, c, w, l) in enumerate( zip(idx, array.shape, array.chunks, pad_width, stat_length)): if i < 1: axes.append(d) select.append(slice(None, l[0], None)) pad_shape.append(w[0]) pad_chunks.append(w[0]) elif i > 1: axes.append(d) select.append(slice(s - l[1], None, None)) pad_shape.append(w[1]) pad_chunks.append(w[1]) else: select.append(slice(None)) pad_shape.append(s) pad_chunks.append(c) axes = tuple(axes) select = tuple(select) pad_shape = tuple(pad_shape) pad_chunks = tuple(pad_chunks) result_idx = array[select] if axes: if mode == "maximum": result_idx = result_idx.max(axis=axes, keepdims=True) elif mode == "mean": result_idx = result_idx.mean(axis=axes, keepdims=True) elif mode == "minimum": result_idx = result_idx.min(axis=axes, keepdims=True) result_idx = broadcast_to(result_idx, pad_shape, chunks=pad_chunks) if mode == "mean": if np.issubdtype(array.dtype, np.integer): result_idx = rint(result_idx) result_idx = result_idx.astype(array.dtype) result[idx] = result_idx result = block(result.tolist()) return result