def k_fold(X): X, Y = read_data('titanic_train.csv') # get first fold index fold_index = len(X) / fold #initialize array of folds fold_indices = [] # add all fold indexes to array for i in range(1, fold + 1): fold_indices.append(i * fold) #initialize array to store all error rates error_rates = [] for f in fold: # read the data # shift it over by the fold index, so partition doesnt include different fold everytime np.roll(X, f) np.roll(Y, f) # train the data with ratio (fold - 1) / fold to split training data into all but 1 fold (X_train, Y_train, X_test, Y_test) = split_data(X, Y, (fold - 1) / fold) options = None model = MyLogisticReg(options, lam) model.fit(X_train, Y_train) y_pred = model.predict(X_test) error_rate = model.evaluate(Y_test, y_pred) # append the error rate from the current fold error_rates.append(error_rate) # get the average error rate by summing and diving for each fold return np.sum(error_rates) / folds
def realign_image(arr, shift): """ Translate and rotate image via Fourier Parameters ---------- arr : ndarray Image array. shift: tuple Mininum and maximum values to rescale data. angle: float, optional Mininum and maximum values to rescale data. Returns ------- ndarray Output array. """ # if both shifts are integers, do circular shift; otherwise perform Fourier shift. if np.count_nonzero(np.abs(np.array(shift) - np.round(shift)) < 0.01) == 2: temp = np.roll(arr, int(shift[0]), axis=0) temp = np.roll(temp, int(shift[1]), axis=1) temp = temp.astype('float32') else: temp = fourier_shift(np.fft.fftn(arr), shift) temp = np.fft.ifftn(temp) temp = np.abs(temp).astype('float32') return temp
def fft_convolve2d(x, y): """ 2D convolution, using FFT""" fr = fft.fft2(x) fr2 = fft.fft2(np.flipud(np.fliplr(y))) m, n = fr.shape cc = np.real(fft.ifft2(fr * fr2)) cc = np.roll(cc, -int(m / 2) + 1, axis=0) cc = np.roll(cc, -int(n / 2) + 1, axis=1) return cc
def total_variation_3d(arr): """ Calculate total variation of a 3D array. :param arr: 3D Tensor. :return: Scalar. """ res = np.sum(np.abs(np.roll(arr, 1, axis=0) - arr)) res = res + np.sum(np.abs(np.roll(arr, 1, axis=1) - arr)) res = res + np.sum(np.abs(np.roll(arr, 1, axis=2) - arr)) return res
def _grid_average_2d(self, eps_vec): eps_grid = self._vec_to_grid(eps_vec) eps_grid_xx = 1 / 2 * (eps_grid + npa.roll(eps_grid, axis=1, shift=1)) eps_grid_yy = 1 / 2 * (eps_grid + npa.roll(eps_grid, axis=0, shift=1)) eps_vec_xx = self._grid_to_vec(eps_grid_xx) eps_vec_yy = self._grid_to_vec(eps_grid_yy) eps_vec_xx = eps_vec_xx eps_vec_yy = eps_vec_yy return eps_vec_xx, eps_vec_yy
def grid_xyz_to_center(Q_xx, Q_yy, Q_zz): """ Computes the interpolated value of the quantitys Q_xx, Q_yy, Q_zz at the center of Yee latice Returns these three components """ # compute the averages Q_xx_avg = (Q_xx.astype('float') + npa.roll(Q_xx, shift=1, axis=0))/2 Q_yy_avg = (Q_yy.astype('float') + npa.roll(Q_yy, shift=1, axis=1))/2 Q_zz_avg = (Q_zz.astype('float') + npa.roll(Q_zz, shift=1, axis=2))/2 return Q_xx_avg, Q_yy_avg, Q_zz_avg
def area(self): # Returns the area of the airfoil, in nondimensional (normalized to chord^2) units. x = self.coordinates[:, 0] y = self.coordinates[:, 1] x_n = np.roll(x, -1) # x_next, or x_i+1 y_n = np.roll(y, -1) # y_next, or y_i+1 a = x * y_n - x_n * y # a is the area of the triangle bounded by a given point, the next point, and the origin. A = 0.5 * np.sum(a) # area return A
def _grid_average_3d(self, eps_vec): eps_grid = self._vec_to_grid(eps_vec) eps_grid_xx = 1 / 2 * (eps_grid + npa.roll(eps_grid, axis=2, shift=1)) eps_grid_yy = 1 / 2 * (eps_grid + npa.roll(eps_grid, axis=1, shift=1)) eps_grid_zz = 1 / 2 * (eps_grid + npa.roll(eps_grid, axis=0, shift=1)) eps_vec_xx = self._grid_to_vec(eps_grid_xx) eps_vec_yy = self._grid_to_vec(eps_grid_yy) eps_vec_zz = self._grid_to_vec(eps_grid_zz) eps_vec_xx = eps_vec_xx eps_vec_yy = eps_vec_yy eps_vec_zz = eps_vec_zz vec = npa.hstack((eps_vec_xx, eps_vec_yy, eps_vec_zz)) return vec
def list_permute(X, Y, k, l, n_permute=400, seed=8273): """ Return a numpy array of HSIC's for each permutation. This is an implementation where kernel matrices are pre-computed. TODO: can be improved. """ if X.shape[0] != Y.shape[0]: raise ValueError( 'X and Y must have the same number of rows (sample size') n = X.shape[0] r = 0 arr_hsic = np.zeros(n_permute) K = k.eval(X, X) L = l.eval(Y, Y) # set the seed rand_state = np.random.get_state() np.random.seed(seed) while r < n_permute: # shuffle the order of X, Y while still keeping the original pairs ind = np.random.choice(n, n, replace=False) Ks = K[np.ix_(ind, ind)] #Xs = X[ind] #Ys = Y[ind] #Ks2 = k.eval(Xs, Xs) #assert np.linalg.norm(Ks - Ks2, 'fro') < 1e-4 Ls = L[np.ix_(ind, ind)] Kmean = np.mean(Ks, 0) HK = Ks - Kmean HKf = HK.flatten() / (n - 1) # shift Ys n-1 times for s in range(n - 1): if r >= n_permute: break Ls = np.roll(Ls, 1, axis=0) Ls = np.roll(Ls, 1, axis=1) # compute HSIC Lmean = np.mean(Ls, 0) HL = Ls - Lmean # t = trace(KHLH) HLf = HL.T.flatten() / (n - 1) bhsic = HKf.dot(HLf) arr_hsic[r] = bhsic r = r + 1 # reset the seed back np.random.set_state(rand_state) return arr_hsic
def neg_grad_FZ(FZ): # shift states out1 = np.dot(get_F_minus_states(FZ), _shift_right_mat) + np.dot( get_F_plus_states(FZ), _shift_left_mat) + get_Z_states(FZ) out2 = out1 + get_F0_minus(np.conj(np.roll(out1, 1, axis=0))) return out2
def test_vector_jacobian_product(): # This function will have an asymmetric jacobian matrix. fun = lambda a: np.roll(np.sin(a), 1) a = npr.randn(5) V = npr.randn(5) J = jacobian(fun)(a) check_equivalent(np.dot(V.T, J), vector_jacobian_product(fun)(a, V))
def test_tensor_jacobian_product(): # This function will have an asymmetric jacobian matrix. fun = lambda a: np.roll(np.sin(a), 1) a = npr.randn(5) V = npr.randn(5) J = jacobian(fun)(a) check_equivalent(np.dot(V.T, J), tensor_jacobian_product(fun)(a, V))
def test_tensor_jacobian_product(): fun = lambda a: np.roll(np.sin(a), 1) a = npr.randn(5, 4, 3) V = npr.randn(5, 4) J = jacobian(fun)(a) check_equivalent(np.tensordot(V, J, axes=np.ndim(V)), tensor_jacobian_product(fun)(a, V))
def identify_curve(curve, index, target, nperiod=288): """Identity nperiod non-negative parameters that optimize the target applied to curves.""" assert curve.shape == (nperiod, ), f"bad curve shape {curve.shape}" assert target.shape == (nperiod, ), f"bad target shape {target.shape}" assert np.shape(index)[0] <= nperiod, f"bad index shape {index.shape}" # First, create a [nperiod, nperiod] matrix X that computes the # curve for each period. We then reduce this to a [nperiod, # len(index)] matrix that sums contributions over each each # window (i.e., groups of columns) defined by the provided index. roll = np.zeros([nperiod, nperiod], dtype=int) curve_index = np.arange(nperiod) for i in range(roll.shape[0]): # Shape the curve at period i. roll[i, :] = np.roll(curve_index, i) X_rolled = curve[roll] X = np.zeros([nperiod, len(index)]) for i, ivs in enumerate(index_to_intervals(index, nperiod=nperiod)): for beg, end in ivs: X[:, i] += np.sum(X_rolled[:, beg:end], axis=1) y = target x, rnorm = optimize.nnls(X, y) return x
def _list_permute_generic(X, Y, k, l, n_permute=400, seed=8273): """ Return a numpy array of HSIC's for each permutation. This is a naive generic implementation where kernel matrices are not pre-computed. """ if X.shape[0] != Y.shape[0]: raise ValueError( 'X and Y must have the same number of rows (sample size') n = X.shape[0] r = 0 arr_hsic = np.zeros(n_permute) # set the seed rand_state = np.random.get_state() np.random.seed(seed) while r < n_permute: # shuffle the order of X, Y while still keeping the original pairs ind = np.random.choice(n, n, replace=False) Xs = X[ind] Ys = Y[ind] # shift Ys n-1 times for s in range(n - 1): if r >= n_permute: break Ys = np.roll(Ys, 1, axis=0) # compute HSIC bhsic = QuadHSIC.biased_hsic(Xs, Ys, k, l) arr_hsic[r] = bhsic r = r + 1 # reset the seed back np.random.set_state(rand_state) return arr_hsic
def centroid(self): # Returns the centroid of the airfoil, in nondimensional (chord-normalized) units. x = self.coordinates[:, 0] y = self.coordinates[:, 1] x_n = np.roll(x, -1) # x_next, or x_i+1 y_n = np.roll(y, -1) # y_next, or y_i+1 a = x * y_n - x_n * y # a is the area of the triangle bounded by a given point, the next point, and the origin. A = 0.5 * np.sum(a) # area x_c = 1 / (6 * A) * np.sum(a * (x + x_n)) y_c = 1 / (6 * A) * np.sum(a * (y + y_n)) centroid = np.array([x_c, y_c]) return centroid
def circulant_2d_vector_to_circulant_2d_matrix(circulant_2d_vector): circulant_2d_matrix = np.asarray([ np.roll(circulant_2d_vector, ii) for ii in range(len(circulant_2d_vector)) ]) return circulant_2d_matrix
def project(vx, vy): """Project the velocity field to be approximately mass-conserving, using a few iterations of Gauss-Seidel.""" p = np.zeros(vx.shape) h = 1.0 / vx.shape[0] div = ( -0.5 * h * (np.roll(vx, -1, axis=0) - np.roll(vx, 1, axis=0) + np.roll(vy, -1, axis=1) - np.roll(vy, 1, axis=1)) ) for k in range(10): p = ( div + np.roll(p, 1, axis=0) + np.roll(p, -1, axis=0) + np.roll(p, 1, axis=1) + np.roll(p, -1, axis=1) ) / 4.0 vx -= 0.5 * (np.roll(p, -1, axis=0) - np.roll(p, 1, axis=0)) / h vy -= 0.5 * (np.roll(p, -1, axis=1) - np.roll(p, 1, axis=1)) / h return vx, vy
def generate_isotropic_circulant_2d_vector(k, autocorr_scale): gaussian = scipy.stats.multivariate_normal(mean=[0, 0]).pdf xs = ys = np.linspace(-autocorr_scale, autocorr_scale, k) Xs, Ys = np.meshgrid(xs, ys) isotropic_circulant_1d = np.asarray( [gaussian([x, y]) for x, y in zip(Xs.flatten(), Ys.flatten())]) isotropic_circulant_1d = np.roll(isotropic_circulant_1d, -np.argmax(isotropic_circulant_1d)) return isotropic_circulant_1d
def grad_FZ(FZ): # shift the states out1 = np.dot(get_F_plus_states(FZ), _shift_right_mat) + np.dot( get_F_minus_states(FZ), _shift_left_mat) + get_Z_states(FZ) # fill in F0+ using a mask out2 = out1 + get_F0_plus(np.conj(np.roll(out1, -1, axis=0))) return out2
def Iyy(self): # Returns the nondimensionalized Iyy moment of inertia, taken about the centroid. x = self.coordinates[:, 0] y = self.coordinates[:, 1] x_n = np.roll(x, -1) # x_next, or x_i+1 y_n = np.roll(y, -1) # y_next, or y_i+1 a = x * y_n - x_n * y # a is the area of the triangle bounded by a given point, the next point, and the origin. A = 0.5 * np.sum(a) # area x_c = 1 / (6 * A) * np.sum(a * (x + x_n)) y_c = 1 / (6 * A) * np.sum(a * (y + y_n)) centroid = np.array([x_c, y_c]) Iyy = 1 / 12 * np.sum(a * (np.power(x, 2) + x * x_n + np.power(x_n, 2))) Ivv = Iyy - A * centroid[0] ** 2 return Ivv
def Ixy(self): # Returns the nondimensionalized product of inertia, taken about the centroid. x = self.coordinates[:, 0] y = self.coordinates[:, 1] x_n = np.roll(x, -1) # x_next, or x_i+1 y_n = np.roll(y, -1) # y_next, or y_i+1 a = x * y_n - x_n * y # a is the area of the triangle bounded by a given point, the next point, and the origin. A = 0.5 * np.sum(a) # area x_c = 1 / (6 * A) * np.sum(a * (x + x_n)) y_c = 1 / (6 * A) * np.sum(a * (y + y_n)) centroid = np.array([x_c, y_c]) Ixy = 1 / 24 * np.sum(a * (x * y_n + 2 * x * y + 2 * x_n * y_n + x_n * y)) Iuv = Ixy - A * centroid[0] * centroid[1] return Iuv
def curl_E(axis, Ex, Ey, Ez, dL): if axis == 0: return (npa.roll(Ez, shift=-1, axis=1) - Ez) / dL - (npa.roll(Ey, shift=-1, axis=2) - Ey) / dL elif axis == 1: return (npa.roll(Ex, shift=-1, axis=2) - Ex) / dL - (npa.roll(Ez, shift=-1, axis=0) - Ez) / dL elif axis == 2: return (npa.roll(Ey, shift=-1, axis=0) - Ey) / dL - (npa.roll(Ex, shift=-1, axis=1) - Ex) / dL
def curl_H(axis, Hx, Hy, Hz, dL): if axis == 0: return (Hz - npa.roll(Hz, shift=1, axis=1)) / dL - (Hy - npa.roll(Hy, shift=1, axis=2)) / dL elif axis == 1: return (Hx - npa.roll(Hx, shift=1, axis=2)) / dL - (Hz - npa.roll(Hz, shift=1, axis=0)) / dL elif axis == 2: return (Hy - npa.roll(Hy, shift=1, axis=0)) / dL - (Hx - npa.roll(Hx, shift=1, axis=1)) / dL
def grad_like(self,wsp,ws,ws_k,xi): #print('start grad_like') conv = np.real(fft.ifft2(ws_k*self.psf_k)); #convolution of ws with psf term1 = (conv - self.data)/self.n_grid**2 /self.sig_noise**2 #term thats squared in like (with N in denom) grad = np.zeros((self.n_grid,self.n_grid),dtype='complex') for i in range(0,self.n_grid): for j in range(0,self.n_grid): #try to modulate by hand ft1 = fft.fft2(1/(1+np.exp(-1*wsp/xi))); ftp = np.roll(ft1,(i,j),axis=(0,1)); term2 = fft.ifft2(ftp*self.psf_k); grad[i,j] = np.sum(term1*term2); grad_real = self.complex_to_real(np.conj(grad.flatten())); #embed to 2R #print('end grad_like'); return grad_real; #return 1d array
def grid_center_to_xyz(Q_mid, averaging=True): """ Computes the interpolated value of the quantity Q_mid felt at the Ex, Ey, Ez positions of the Yee latice Returns these three components """ # initialize Q_xx = copy.copy(Q_mid) Q_yy = copy.copy(Q_mid) Q_zz = copy.copy(Q_mid) # if averaging, set the respective xx, yy, zz components to the midpoint in the Yee lattice. if averaging: # get the value from the middle of the next cell over Q_x_r = npa.roll(Q_mid, shift=1, axis=0) Q_y_r = npa.roll(Q_mid, shift=1, axis=1) Q_z_r = npa.roll(Q_mid, shift=1, axis=2) # average with the two middle values Q_xx = (Q_mid + Q_x_r)/2 Q_yy = (Q_mid + Q_y_r)/2 Q_zz = (Q_mid + Q_z_r)/2 return Q_xx, Q_yy, Q_zz
def attribute_parameters(curve, index, values, nparam=24, nperiod=288): assert curve.shape == (nperiod, ), f"bad curve shape {curve.shape}" roll = np.zeros([nperiod, nperiod], dtype=int) curve_index = np.flip(np.arange(nperiod)) for i in range(roll.shape[0]): # Shape the curve at period i. roll[i, :] = np.roll(curve_index, i + 1) X = curve[roll] for i, ivs in enumerate(index_to_intervals(index, nperiod=nperiod)): for beg, end in ivs: X[:, beg:end] *= values[i] # np.sum(X_rolled[:, beg:end], axis=1) x = np.sum(X, axis=1) x = np.mean(np.reshape(x, (nparam, nperiod // nparam)), axis=1) return x
import warnings N_states = 10 # number of states to preserve for EPG # helper function for accessing number of states def get_N_states_epg(): return N_states # Because we are using autograd, we have to avoid assignment, so we implement # some epg operations as matrix multiplications and use masks. Here we define some mask functions # in the module so that we don't have to precompute them every time # create a matrix that is size 3 x N_states, for shifting without wrap, put ones in off diagonals _shift_right_mat = np.roll(np.identity(N_states), 1, axis=1) _shift_right_mat[:, 0] = 0 _shift_left_mat = np.roll(np.identity(N_states), -1, axis=1) _shift_left_mat[:, -1] = 0 _mask_F_plus = np.zeros((3, N_states)) _mask_F_plus[0, :] = 1. _mask_F_minus = np.zeros((3, N_states)) _mask_F_minus[1, :] = 1. _mask_Z = np.zeros((3, N_states)) _mask_Z[2, :] = 1. _F0_plus_mask = np.zeros((3, N_states))
def fun(x): return to_scalar(np.roll(x, 2, axis=1))
def project(vx, vy): """Project the velocity field to be approximately mass-conserving, using a few iterations of Gauss-Seidel.""" p = np.zeros(vx.shape, dtype=dtype) h = 1.0 / vx.shape[0] div = -0.5 * h * (np.roll(vx, -1, axis=0) - np.roll(vx, 1, axis=0) + np.roll(vy, -1, axis=1) - np.roll(vy, 1, axis=1)) for k in range(6): p = (div + np.roll(p, 1, axis=0) + np.roll(p, -1, axis=0) + np.roll(p, 1, axis=1) + np.roll(p, -1, axis=1)) / 4.0 vx -= 0.5 * (np.roll(p, -1, axis=0) - np.roll(p, 1, axis=0)) / h vy -= 0.5 * (np.roll(p, -1, axis=1) - np.roll(p, 1, axis=1)) / h return vx, vy
anp.tanh.defjvp(lambda g, ans, gvs, vs, x: g / anp.cosh(x)**2) anp.arcsinh.defjvp(lambda g, ans, gvs, vs, x: g / anp.sqrt(x**2 + 1)) anp.arccosh.defjvp(lambda g, ans, gvs, vs, x: g / anp.sqrt(x**2 - 1)) anp.arctanh.defjvp(lambda g, ans, gvs, vs, x: g / (1 - x**2)) anp.rad2deg.defjvp(lambda g, ans, gvs, vs, x: g / anp.pi * 180.0) anp.degrees.defjvp(lambda g, ans, gvs, vs, x: g / anp.pi * 180.0) anp.deg2rad.defjvp(lambda g, ans, gvs, vs, x: g * anp.pi / 180.0) anp.radians.defjvp(lambda g, ans, gvs, vs, x: g * anp.pi / 180.0) anp.square.defjvp(lambda g, ans, gvs, vs, x: g * 2 * x) anp.sqrt.defjvp(lambda g, ans, gvs, vs, x: g * 0.5 * x**-0.5) anp.sinc.defjvp(lambda g, ans, gvs, vs, x: g * (anp.cos( anp.pi * x) * anp.pi * x - anp.sin(anp.pi * x)) / (anp.pi * x**2)) anp.reshape.defjvp(lambda g, ans, gvs, vs, x, shape, order=None: anp.reshape( g, vs.shape, order=order)) anp.roll.defjvp( lambda g, ans, gvs, vs, x, shift, axis=None: anp.roll(g, shift, axis=axis)) anp.array_split.defjvp(lambda g, ans, gvs, vs, ary, idxs, axis=0: anp. array_split(g, idxs, axis=axis)) anp.split.defjvp( lambda g, ans, gvs, vs, ary, idxs, axis=0: anp.split(g, idxs, axis=axis)) anp.vsplit.defjvp(lambda g, ans, gvs, vs, ary, idxs: anp.vsplit(g, idxs)) anp.hsplit.defjvp(lambda g, ans, gvs, vs, ary, idxs: anp.hsplit(g, idxs)) anp.dsplit.defjvp(lambda g, ans, gvs, vs, ary, idxs: anp.dsplit(g, idxs)) anp.ravel.defjvp( lambda g, ans, gvs, vs, x, order=None: anp.ravel(g, order=order)) anp.expand_dims.defjvp( lambda g, ans, gvs, vs, x, axis: anp.expand_dims(g, axis)) anp.squeeze.defjvp(lambda g, ans, gvs, vs, x, axis=None: anp.squeeze(g, axis)) anp.diag.defjvp(lambda g, ans, gvs, vs, x, k=0: anp.diag(g, k)) anp.flipud.defjvp(lambda g, ans, gvs, vs, x, : anp.flipud(g)) anp.fliplr.defjvp(lambda g, ans, gvs, vs, x, : anp.fliplr(g))
def project(vx, vy, occlusion, width=0.4): """Project the velocity field to be approximately mass-conserving. Technically we are finding an approximate solution to the Poisson equation.""" p = np.zeros(vx.shape) div = -0.5 * (np.roll(vx, -1, axis=1) - np.roll(vx, 1, axis=1) + np.roll(vy, -1, axis=0) - np.roll(vy, 1, axis=0)) div = filter(div, occlusion, width=width) for k in range( 50): # use gauss-seidel to approximately solve linear system p = (div + np.roll(p, 1, axis=1) + np.roll(p, -1, axis=1) + np.roll(p, 1, axis=0) + np.roll(p, -1, axis=0)) / 4.0 p = filter(p, occlusion, width=width) vx = vx - 0.5 * (np.roll(p, -1, axis=1) - np.roll(p, 1, axis=1)) vy = vy - 0.5 * (np.roll(p, -1, axis=0) - np.roll(p, 1, axis=0)) vx = occlude(vx, occlusion) vy = occlude(vy, occlusion) return vx, vy
def test_matrix_jacobian_product(): fun = lambda a: np.roll(np.sin(a), 1) a = npr.randn(5, 4) V = npr.randn(5, 4) J = jacobian(fun)(a) check_equivalent(np.tensordot(V, J), vector_jacobian_product(fun)(a, V))
def make_continuous(f, occlusion): non_occluded = 1 - occlusion num = np.roll(f, 1, axis=0) * np.roll(non_occluded, 1, axis=0)\ + np.roll(f, -1, axis=0) * np.roll(non_occluded, -1, axis=0)\ + np.roll(f, 1, axis=1) * np.roll(non_occluded, 1, axis=1)\ + np.roll(f, -1, axis=1) * np.roll(non_occluded, -1, axis=1) den = np.roll(non_occluded, 1, axis=0)\ + np.roll(non_occluded, -1, axis=0)\ + np.roll(non_occluded, 1, axis=1)\ + np.roll(non_occluded, -1, axis=1) return f * non_occluded + (1 - non_occluded) * num / ( den + 0.001)
def test_tensor_jacobian_product(): fun = lambda a: np.roll(np.sin(a), 1) a = npr.randn(5, 4, 3) V = npr.randn(5, 4) J = jacobian(fun)(a) check_equivalent(np.tensordot(V, J, axes=np.ndim(V)), vector_jacobian_product(fun)(a, V))
def fun(x): return to_scalar(np.roll(x, 2, axis=1)) d_fun = lambda x : to_scalar(grad(fun)(x))
def project(vx, vy, occlusion): """Project the velocity field to be approximately mass-conserving, using a few iterations of Gauss-Seidel.""" p = np.zeros(vx.shape) div = -0.5 * (np.roll(vx, -1, axis=1) - np.roll(vx, 1, axis=1) + np.roll(vy, -1, axis=0) - np.roll(vy, 1, axis=0)) div = make_continuous(div, occlusion) for k in range(50): p = (div + np.roll(p, 1, axis=1) + np.roll(p, -1, axis=1) + np.roll(p, 1, axis=0) + np.roll(p, -1, axis=0))/4.0 p = make_continuous(p, occlusion) vx = vx - 0.5*(np.roll(p, -1, axis=1) - np.roll(p, 1, axis=1)) vy = vy - 0.5*(np.roll(p, -1, axis=0) - np.roll(p, 1, axis=0)) vx = occlude(vx, occlusion) vy = occlude(vy, occlusion) return vx, vy