def function_wrapper(x, b, axis=0, **kwargs): # add the padding to the array xsize = x.shape[axis] if 'pad' in kwargs and kwargs['pad']: npad = b.shape[axis] // 2 padd = cp.take(x, cp.arange(npad), axis=axis) * 0 if kwargs['pad'] == 'zeros': x = cp.concatenate((padd, x, padd), axis=axis) if kwargs['pad'] == 'constant': x = cp.concatenate((padd * 0 + cp.mean(x[:npad]), x, padd + cp.mean(x[-npad:])), axis=axis) if kwargs['pad'] == 'flip': pad_in = cp.flip(cp.take(x, cp.arange(1, npad + 1), axis=axis), axis=axis) pad_out = cp.flip(cp.take(x, cp.arange(xsize - npad - 1, xsize - 1), axis=axis), axis=axis) x = cp.concatenate((pad_in, x, pad_out), axis=axis) # run the convolution y = fcn_convolve(x, b, **kwargs) # remove padding from both arrays (necessary for x ?) if 'pad' in kwargs and kwargs['pad']: # remove the padding y = cp.take(y, cp.arange(npad, x.shape[axis] - npad), axis=axis) x = cp.take(x, cp.arange(npad, x.shape[axis] - npad), axis=axis) assert xsize == x.shape[axis] assert xsize == y.shape[axis] return y
def transform(self, X): """[summary]. Args: X (cupy.ndarray): [description]. Returns: cupy.ndarray: [description]. """ check_is_fitted(self, "class_means_") # TODO(smly): # X = column_or_1d(X, warn=True) # Label encoding if necessary if self._label_encoding_uniques is not None: X = self._label_encoding_uniques.get_indexer(X.to_pandas()) X = cupy.asarray(X) missing_mask = cupy.isnan(X) encode_mask = cupy.invert(missing_mask) unseen_mask = cupy.bitwise_xor( cupy.isin(X, self.classes_, invert=True), missing_mask) X = X.copy() X[unseen_mask] = cupy.max(self.classes_) indices = _get_index_cupy(self.classes_, X[encode_mask]) _classes_index_list = cupy.searchsorted(self.lut_[:, 0], self.classes_) encoded_values = cupy.zeros(X.shape[0], dtype=cupy.float32) encoded_values[encode_mask] = cupy.take( self.lut_[:, 1], cupy.take(_classes_index_list, indices)) encoded_values[unseen_mask] = self.default_unseen_ return encoded_values
def mmr( doc_embedding, word_embeddings, words, top_n=5, diversity=0.8, ): """ Calculate Maximal Marginal Relevance (MMR) between candidate keywords and the document. MMR considers the similarity of keywords/keyphrases with the document, along with the similarity of already selected keywords and keyphrases. This results in a selection of keywords that maximize their within diversity with respect to the document. Arguments: doc_embedding: The document embeddings word_embeddings: The embeddings of the selected candidate keywords/phrases words: The selected candidate keywords/keyphrases top_n: The number of keywords/keyhprases to return diversity: How diverse the select keywords/keyphrases are. Values between 0 and 1 with 0 being not diverse at all and 1 being most diverse. Returns: List[str]: The selected keywords/keyphrases """ # Extract similarity within words, and between words and the document word_doc_similarity = 1 - pairwise_distances( word_embeddings, doc_embedding, metric="cosine") word_similarity = 1 - pairwise_distances(word_embeddings, metric="cosine") # Initialize candidates and already choose best keyword/keyphras keywords_idx = cp.argmax(word_doc_similarity) target = cp.take(keywords_idx, 0) candidates_idx = [i for i in range(len(words)) if i != target] for i in range(top_n - 1): candidate_similarities = word_doc_similarity[candidates_idx, :] if i == 0: first_row = cp.reshape( word_similarity[candidates_idx][:, keywords_idx], (word_similarity[candidates_idx][:, keywords_idx].shape[0], 1)) target_similarities = cp.max(first_row, axis=1) else: target_similarities = cp.max( word_similarity[candidates_idx][:, keywords_idx], axis=1) # Calculate MMR mmr = ( 1 - diversity ) * candidate_similarities - diversity * target_similarities.reshape( -1, 1) mmr_idx = cp.take(cp.array(candidates_idx), cp.argmax(mmr)) # Update keywords & candidates keywords_idx = cp.append(keywords_idx, mmr_idx) candidates_idx.remove(mmr_idx) return [words[idx] for idx in keywords_idx.get()]
def _boolrelextrema(data, comparator, axis=0, order=1, mode="clip"): """ Calculate the relative extrema of `data`. Relative extrema are calculated by finding locations where ``comparator(data[n], data[n+1:n+order+1])`` is True. Parameters ---------- data : ndarray Array in which to find the relative extrema. comparator : callable Function to use to compare two data points. Should take two arrays as arguments. axis : int, optional Axis over which to select from `data`. Default is 0. order : int, optional How many points on each side to use for the comparison to consider ``comparator(n,n+x)`` to be True. Returns ------- extrema : ndarray Boolean array of the same shape as `data` that is True at an extrema, False otherwise. See also -------- argrelmax, argrelmin """ if (int(order) != order) or (order < 1): raise ValueError("Order must be an int >= 1") if data.ndim < 3: results = cp.empty(data.shape, dtype=bool) _peak_finding(data, comparator, axis, order, mode, results) else: datalen = data.shape[axis] locs = cp.arange(0, datalen) results = cp.ones(data.shape, dtype=bool) main = cp.take(data, locs, axis=axis) for shift in cp.arange(1, order + 1): if mode == "clip": p_locs = cp.clip(locs + shift, a_max=(datalen - 1)) m_locs = cp.clip(locs - shift, a_min=0) else: p_locs = locs + shift m_locs = locs - shift plus = cp.take(data, p_locs, axis=axis) minus = cp.take(data, m_locs, axis=axis) results &= comparator(main, plus) results &= comparator(main, minus) if ~results.any(): return results return results
def per_item_gpu(vector_r, matrix_A, matrix_B, matrix_BT, alpha): import cupy as cp from cupy.linalg import inv as gpu_inv vector_r_index = vector_r.nonzero()[0] vector_r_small = cp.array(vector_r.data) vector_c_small = alpha * vector_r_small matrix_B_small = cp.take(matrix_B, vector_r_index, axis=0) matrix_BT_small = cp.take(matrix_BT, vector_r_index, axis=1) denominator = gpu_inv(matrix_A+(matrix_BT_small*vector_c_small).dot(matrix_B_small)) return (denominator.dot(matrix_BT_small)).dot((vector_c_small*vector_r_small+vector_r_small)).flatten()
def conditional_value(self, p_cond_attr, p_cond_value): # print(self.domain.attr_list, p_cond_attr, p_cond_value) cond_attr = [] cond_value = [] for i in range(len(p_cond_attr)): if p_cond_attr[i] in self.domain.attr_list: cond_attr.append(p_cond_attr[i]) cond_value.append(p_cond_value[i]) # print(cond_attr, cond_value) index_list = self.domain.index_list(cond_attr) temp_value = self.values.copy() shape = list(temp_value.shape) # print(f'original shape: {shape}') # print(index_list) for i in range(len(index_list)): axis = index_list[i] shape[axis] = 1 temp_value = cp.take(temp_value, cond_value[i], axis=axis) # print(temp_value.shape, shape) temp_value = temp_value.reshape(shape) shape = [item for item in shape if item != 1] temp_value = temp_value.reshape(shape) return Factor(self.domain.invert(cond_attr), temp_value)
def cmplx_sort(p): """Sort roots based on magnitude. Parameters ---------- p : array_like The roots to sort, as a 1-D array. Returns ------- p_sorted : ndarray Sorted roots. indx : ndarray Array of indices needed to sort the input `p`. Examples -------- >>> import cusignal >>> vals = [1, 4, 1+1.j, 3] >>> p_sorted, indx = cusignal.cmplx_sort(vals) >>> p_sorted array([1.+0.j, 1.+1.j, 3.+0.j, 4.+0.j]) >>> indx array([0, 2, 3, 1]) """ p = cp.asarray(p) if cp.iscomplexobj(p): indx = cp.argsort(abs(p)) else: indx = cp.argsort(p) return cp.take(p, indx, 0), indx
class BackendCupy: @staticmethod def init(): cp.random.seed(_SEED) as_tensor = cp.asarray index_select = lambda a, axis, inds: cp.take(a, inds, axis) reshape = cp.reshape sum = cp.sum unsqueeze = cp.expand_dims tile = cp.tile concat = cp.concatenate matmul = cp.matmul squeeze = cp.squeeze swapaxes = cp.swapaxes log = cp.log mean = cp.mean sigmoid = lambda x: 1. / (1. + cp.exp(-x)) zero_scalar = lambda: cp.array(0., dtype=cp.float32) as_numpy = cp.asnumpy @staticmethod def hybrid_sparse_2d(index_all, grads_all, shape): num_row = index_all.shape[0] emb_size = shape[-1] # (data, (row, col)) x = cp.sparse.coo_matrix((grads_all.reshape(-1), (cp.repeat( index_all, emb_size), cp.tile(cp.arange(emb_size), num_row))), shape=shape, dtype=cp.float32) return x
def fetch_optim(user, tabular_np, neighbors_indeces): optim_indeces = cupy.where(tabular_np[user] == 0)[0] for i in neighbors_indeces: optim_indeces = cupy.unique( cupy.concatenate((optim_indeces, cupy.where(tabular_np[i] > 0)[0]), 0)) optim_values = cupy.take(tabular_np, optim_indeces, axis=1) return optim_values, optim_indeces
def shuffle(tensor, axis=0): """Shuffle in place a tensor along a given axis. Other axis remain in place. Args: tensor (ndarray): tensor to shuffle. axis (int, optional): axis to shuffle on. Default to 0. Returns: None: in place shuffling """ if not axis: cp.random.shuffle(tensor) else: size = tensor.shape[axis] # cupy don't support new numpy rng system, so have to do it ourselves. cp.take(tensor, cp.random.rand(size).argsort(), axis=axis, out=tensor)
def shuffle(tensor, axis=0): """Shuffle in place a tensor along a given axis. Other axis remain in place. Args: tensor (ndarray): tensor to shuffle. axis (int, optional): axis to shuffle on. Default to 0. Returns: Tensor: shuffled tensor """ # ! we must return the tensor because other backend don't do shuffle # ! in place. if not axis: cp.random.shuffle(tensor) else: size = tensor.shape[axis] # cupy don't support new numpy rng system, so have to do it ourselves. cp.take(tensor, cp.random.rand(size).argsort(), axis=axis, out=tensor) return tensor
def adjoint(self, add, model, data): """Extract non-zero subsequence""" self.checkDomainRange(model, data) if add: temp = model.clone() x = data.clone().getNdArray() for ax, pad in enumerate(self.pad): x = cp.take(x, pad[0] + cp.arange(self.dims[ax]), axis=ax) model.arr = x if add: model.scaleAdd(temp, 1., 1.) return
def lanczos4_zoom(image_mat: cp.array) -> cp.array: """the function to zoom image matrix""" number_of_files = image_mat.shape[0] # First interpolate in Y direction mat_temp = cp.zeros((number_of_files, w, int(h * mag)), dtype=cp.float32) for Qi, ui in zip(Qy, uy): cp.add(mat_temp, cp.transpose(cp.take(image_mat, ui, axis=1), (0, 2, 1)) * Qi, out=mat_temp) del image_mat # Then interpolate in X direction mat_zoomed = cp.zeros((number_of_files, int(h * mag), int(w * mag)), dtype=cp.float32) for Qi, ui in zip(Qx, ux): cp.add(mat_zoomed, cp.transpose(cp.take(mat_temp, ui, axis=1), (0, 2, 1)) * Qi, out=mat_zoomed) del mat_temp return mat_zoomed
def take_array(arr, indices, axis=None): assert len(arr) > 0 if CumlToolBox.is_cudf_series(arr): return arr.take(indices, keep_index=False) atype = type(arr[0]).__name__ if atype.find('int') >= 0 or atype.find('float') >= 0: return cupy.take(cupy.array(arr), indices=cupy.array(indices), axis=axis) else: arr = cudf.from_pandas(pd.Series(arr)) return arr.take(indices, keep_index=False)
def fliplr(a): """Flip array in the left/right direction. Flip the entries in each row in the left/right direction. Columns are preserved, but appear in a different order than before. Args: a (~cupy.ndarray): Input array. Returns: ~cupy.ndarray: Output array. .. seealso:: :func:`numpy.fliplr` """ return cupy.take(a, cupy.arange(a.shape[1] - 1, -1, -1), axis=1)
def flipud(a): """Flip array in the up/down direction. Flip the entries in each column in the up/down direction. Rows are preserved, but appear in a different order than before. Args: a (~cupy.ndarray): Input array. Returns: ~cupy.ndarray: Output array. .. seealso:: :func:`numpy.flipud` """ return cupy.take(a, cupy.arange(a.shape[0] - 1, -1, -1), axis=0)
def flipud(a): """Flip array in the up/down direction. Flip the entries in each column in the up/down direction. Rows are preserved, but appear in a different order than before. Args: a (~cupy.ndarray): Input array. Returns: ~cupy.ndarray: Output array. .. seealso:: :func:`numpy.flipud` """ if a.ndim < 1: raise ValueError('Input must be >= 1-d') return cupy.take(a, cupy.arange(a.shape[0] - 1, -1, -1), axis=0)
def take(t, indices, axis=None, out=None): """Takes elements of a Tensor at specified indices along a specified axis Args: tensor (ndarray): Tensor to extract elements from. indices (int or array-like): Indices of elements that this function takes. axis (int, optional): The axis along which to select indices from. The flattened input is used by default. Defaults to None. Returns: ndarray: Tensor containing the values from the specified indices. """ if not is_tensor(t): t = tensor(t) return cp.take(t, indices, axis=0)
def fliplr(a): """Flip array in the left/right direction. Flip the entries in each row in the left/right direction. Columns are preserved, but appear in a different order than before. Args: a (~cupy.ndarray): Input array. Returns: ~cupy.ndarray: Output array. .. seealso:: :func:`numpy.fliplr` """ if a.ndim < 2: raise ValueError('Input must be >= 2-d') return cupy.take(a, cupy.arange(a.shape[1] - 1, -1, -1), axis=1)
def take(tensor, indices, axis=None, out=None): """Takes elements of a Tensor at specified indices along a specified axis Args: tensor (ndarray): Tensor to extract elements from. indices (int or array-like): Indices of elements that this function takes. axis (int, optional): The axis along which to select indices from. The flattened input is used by default. Defaults to None. out (ndarray. Optional): Output array. If provided, it should be of appropriate shape and dtype. Defaults to None. Returns: ndarray: Tensor containing the values from the specified indices. """ return cp.take(tensor, indices, axis=axis, out=out)
def get_slice(self, theta_n, phi_n, dist_n): theta = theta_n*math.pi phi = math.radians(phi_n*PHI_MAX) dist = dist_n*self.x0/2 # +/- 104 pixels # --- 1: Get bounding box dims --- h1, h2, z_min, z_max = self.get_bounding_box(theta=theta, phi=phi, dist=dist) w = self.y0 h = self.z0 # --- 2: Extract slice from volume --- # Get x_i and y_i for current layer x_offsets = cp.linspace(-h/2, h/2, h) * math.sin(phi) * math.cos(theta) y_offsets = cp.linspace(-h/2, h/2, h) * math.sin(phi) * math.sin(theta) # Tile and transpose x_offsets = cp.transpose(cp.tile(x_offsets,(w,1))) y_offsets = cp.transpose(cp.tile(y_offsets,(w,1))) x_i = cp.tile(cp.linspace(h1[0], h2[0], w),(h,1)) x_i = cp.asnumpy(cp.array(cp.rint(x_i + x_offsets),dtype='int')) y_i = cp.tile(cp.linspace(h1[1], h2[1], w),(h,1)) y_i = cp.asnumpy(cp.array(cp.rint(y_i + y_offsets),dtype='int')) # Don't forget to include the index offset from z! z_i = cp.transpose(cp.tile(cp.linspace(z_min, z_max, h),(w,1))) z_i = cp.asnumpy(cp.array(cp.rint(z_i),dtype='int')) # Flatten flat_inds = np.ravel_multi_index((x_i,y_i,z_i),(self.x0,self.y0,self.z0),mode='clip') # Fill in entire slice at once slice = cp.take(cp.array(self.data), cp.array(flat_inds)) # --- 3: Mask slice --- slice = cp.multiply(slice, cp.array(self.mask)) return cp.asnumpy(slice)
def fetch_neighborhood(user, tabular_np, k): user_vector, user_indeces = fetch_user_vector(user, tabular_np) data_vector = cupy.take(tabular_np, user_indeces, axis=1).astype(cupy.int64) neighbors_data = cupy.zeros(k, dtype=cupy.float64) neighbors_indeces = cupy.zeros(k, dtype=int) for i in range(data_vector.shape[0]): if i != user: pearson = evaluate_chromosome(data_vector[i][0], user_vector) # check if the given vectors have the same non-zero indeces if cupy.equal( cupy.where(user_vector == 0)[0].shape, cupy.where(data_vector[i][0] == 0)[0].shape): if cupy.equal( cupy.where(user_vector == 0)[0], cupy.where(data_vector[i][0] == 0)[0]): # adjust pearson coefficient to minimum for we do not want that vector to be chosen pearson = -2 print( 'Warning [2]: Same indeces are evaluated [at fetch neighborhood]' ) # sort pearson correlation coefficients for a in range(k): for b in range(k): if neighbors_data[a] < neighbors_data[b]: tmp = neighbors_data[b] neighbors_data[b] = neighbors_data[a] neighbors_data[a] = tmp tmp = neighbors_indeces[b] neighbors_indeces[b] = neighbors_indeces[a] neighbors_indeces[a] = tmp # check if greater pearson coefficient was found for j in range(k): if neighbors_data[j] < pearson: neighbors_data[j] = pearson neighbors_indeces[j] = i break return neighbors_data, neighbors_indeces
def detrend(data, axis=-1, type="linear", bp=0, overwrite_data=False): """ Remove linear trend along axis from data. Parameters ---------- data : array_like The input data. axis : int, optional The axis along which to detrend the data. By default this is the last axis (-1). type : {'linear', 'constant'}, optional The type of detrending. If ``type == 'linear'`` (default), the result of a linear least-squares fit to `data` is subtracted from `data`. If ``type == 'constant'``, only the mean of `data` is subtracted. bp : array_like of ints, optional A sequence of break points. If given, an individual linear fit is performed for each part of `data` between two break points. Break points are specified as indices into `data`. overwrite_data : bool, optional If True, perform in place detrending and avoid a copy. Default is False Returns ------- ret : ndarray The detrended input data. Examples -------- >>> import cusignal >>> import cupy as cp >>> randgen = cp.random.RandomState(9) >>> npoints = 1000 >>> noise = randgen.randn(npoints) >>> x = 3 + 2*cp.linspace(0, 1, npoints) + noise >>> (cusignal.detrend(x) - noise).max() < 0.01 True """ if type not in ["linear", "l", "constant", "c"]: raise ValueError("Trend type must be 'linear' or 'constant'.") data = asarray(data) dtype = data.dtype.char if dtype not in "dfDF": dtype = "d" if type in ["constant", "c"]: ret = data - expand_dims(mean(data, axis), axis) return ret else: dshape = data.shape N = dshape[axis] bp = sort(unique(r_[0, bp, N])) if cp.any(bp > N): raise ValueError( "Breakpoints must be less than length of \ data along given axis." ) Nreg = len(bp) - 1 # Restructure data so that axis is along first dimension and # all other dimensions are collapsed into second dimension rnk = len(dshape) if axis < 0: axis = axis + rnk newdims = np.r_[axis, 0:axis, axis + 1 : rnk] newdata = reshape( transpose(data, tuple(newdims)), (N, _prod(dshape) // N) ) if not overwrite_data: newdata = newdata.copy() # make sure we have a copy if newdata.dtype.char not in "dfDF": newdata = newdata.astype(dtype) # Find leastsq fit and remove it for each piece for m in range(Nreg): Npts = int(bp[m + 1] - bp[m]) A = ones((Npts, 2), dtype) A[:, 0] = arange(1, Npts + 1) * 1.0 / Npts sl = slice(bp[m], bp[m + 1]) coef, resids, rank, s = linalg.lstsq(A, newdata[sl]) newdata[sl] = newdata[sl] - dot(A, coef) # Put data back in original shape. tdshape = take(asarray(dshape), asarray(newdims), 0) ret = reshape(newdata, tuple(cp.asnumpy(tdshape))) vals = list(range(1, rnk)) olddims = vals[:axis] + [0] + vals[axis:] ret = transpose(ret, tuple(cp.asnumpy(olddims))) return ret
def test(): #cupy.take(d_arr, c_indices, out=d_arr) c_arg = cupy.argsort(d_arr) cupy.take(d_x, c_arg, axis=0, out=out)
def _init_nd_shape_and_axes(x, shape, axes): """Handle shape and axes arguments for n-dimensional transforms. Returns the shape and axes in a standard form, taking into account negative values and checking for various potential errors. Parameters ---------- x : array_like The input array. shape : int or array_like of ints or None The shape of the result. If both `shape` and `axes` (see below) are None, `shape` is ``x.shape``; if `shape` is None but `axes` is not None, then `shape` is ``scipy.take(x.shape, axes, axis=0)``. If `shape` is -1, the size of the corresponding dimension of `x` is used. axes : int or array_like of ints or None Axes along which the calculation is computed. The default is over all axes. Negative indices are automatically converted to their positive counterpart. Returns ------- shape : array The shape of the result. It is a 1D integer array. axes : array The shape of the result. It is a 1D integer array. """ x = asarray(x) noshape = shape is None noaxes = axes is None if noaxes: axes = arange(x.ndim, dtype=intc) else: axes = atleast_1d(axes) if axes.size == 0: axes = axes.astype(intc) if not axes.ndim == 1: raise ValueError("when given, axes values must be a scalar or vector") if not issubdtype(axes.dtype, integer): raise ValueError("when given, axes values must be integers") axes = where(axes < 0, axes + x.ndim, axes) if axes.size != 0 and (axes.max() >= x.ndim or axes.min() < 0): raise ValueError("axes exceeds dimensionality of input") if axes.size != 0 and unique(axes).shape != axes.shape: raise ValueError("all axes must be unique") if not noshape: shape = atleast_1d(shape) elif isscalar(x): shape = array([], dtype=intc) elif noaxes: shape = array(x.shape, dtype=intc) else: shape = take(x.shape, axes) if shape.size == 0: shape = shape.astype(intc) if shape.ndim != 1: raise ValueError("when given, shape values must be a scalar or vector") if not issubdtype(shape.dtype, integer): raise ValueError("when given, shape values must be integers") if axes.shape != shape.shape: raise ValueError("when given, axes and shape arguments" " have to be of the same length") shape = where(shape == -1, array(x.shape)[axes], shape) if shape.size != 0 and (shape < 1).any(): raise ValueError( "invalid number of data points ({0}) specified".format(shape)) return shape, axes
def lanczos4_zoom_wrapper(images: cp.array, mag: float): """closure. It will return a function to zoom the images, but the parameters will not be calculated again""" # init the parameters for lanczos image resize afterwards h, w = images.shape[1:3] lanczos4_core_lut = generate_lanczos4_weights_lut() yCoordinate = cp.linspace(0, h - 1 / mag, int(h * mag), dtype=cp.float32) t, u = cp.modf(yCoordinate) u = u.astype(int) # select 8 sampling points uy = [ cp.maximum(u - 3, 0), cp.maximum(u - 2, 0), cp.maximum(u - 1, 0), cp.minimum(u, h - 1), cp.minimum(u + 1, h - 1), cp.minimum(u + 2, h - 1), cp.minimum(u + 3, h - 1), cp.minimum(u + 4, h - 1), ] Q = cp.take(lanczos4_core_lut, (t * 1024).astype(int), axis=0) Qy = [cp.take(Q, i, axis=1) for i in range(8)] xCoordinate = cp.linspace(0, w - 1 / mag, int(w * mag), dtype=cp.float32) del t, u, xCoordinate t, u = cp.modf(xCoordinate) u = u.astype(int) # select 8 sampling points ux = [ cp.maximum(u - 3, 0), cp.maximum(u - 2, 0), cp.maximum(u - 1, 0), cp.minimum(u, w - 1), cp.minimum(u + 1, w - 1), cp.minimum(u + 2, w - 1), cp.minimum(u + 3, w - 1), cp.minimum(u + 4, w - 1), ] Q = cp.take(lanczos4_core_lut, (t * 1024).astype(int), axis=0) Qx = [cp.take(Q, i, axis=1) for i in range(8)] del t, u, yCoordinate, Q, lanczos4_core_lut def lanczos4_zoom(image_mat: cp.array) -> cp.array: """the function to zoom image matrix""" number_of_files = image_mat.shape[0] # First interpolate in Y direction mat_temp = cp.zeros((number_of_files, w, int(h * mag)), dtype=cp.float32) for Qi, ui in zip(Qy, uy): cp.add(mat_temp, cp.transpose(cp.take(image_mat, ui, axis=1), (0, 2, 1)) * Qi, out=mat_temp) del image_mat # Then interpolate in X direction mat_zoomed = cp.zeros((number_of_files, int(h * mag), int(w * mag)), dtype=cp.float32) for Qi, ui in zip(Qx, ux): cp.add(mat_zoomed, cp.transpose(cp.take(mat_temp, ui, axis=1), (0, 2, 1)) * Qi, out=mat_zoomed) del mat_temp return mat_zoomed return lanczos4_zoom